java读取win10 chrome(80+) cookie

需求:win10系统,通过java程序来读取chrome的cookie

1. 寻找chrome存放cookie的文件

根据 https://stackoverflow.com/questions/57831923/how-do-i-read-chrome-cookies-file 可知chrome的cookies文件存放在:

String cookieFileLocation = System.getProperty("user.home")+"/AppData/Local/Google/Chrome/User Data/Default/Cookies";

2. 读取cookie文件内容

Cookies本身是一个sqlite数据库,因此,读取cookie的内容转为了读取数据库内容

1. 安装驱动

Github : https://github.com/xerial/sqlite-jdbc

Maven :

<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
    <version>3.31.1</version>
</dependency>

2.读取数据库

try(Connection connection = DriverManager.getConnection("jdbc:sqlite:"+cookieFileLocation)){
    try(PreparedStatement stmt = connection.prepareStatement("SELECT encrypted_value FROM cookies where host_key = 'host_key' and name = 'cookie name'")){
        try(ResultSet rs = stmt.executeQuery()){
            if (rs.next()) {
                byte[] encrypted_value = rs.getBytes("encrypted_value");
            }
        }
    }
}

通过对数据库的读取,可以发现这里的值是加密处理过的

3. 解密

https://stackoverflow.com/questions/60416350/chrome-80-how-to-decode-cookies

1. 获取用于解密的key

根据上面文章,解密的key存储于 /AppData/Local/Google/Chrome/User Data/Local State

String location = System.getProperty("user.home")+"/AppData/Local/Google/Chrome/User Data/Local State";
Path p = Paths.get(location);
ExpressionExecutor ee = Utils.readJson(Files.readString(p));
String key = ee.execute("os_crypt->encrypted_key").get();

2. 解密解密key

我们得到的key字符串也是一个加密后的文本,要想使用它,还得先解密

byte [] base64Array = Base64.getDecoder().decode(key);
base64Array = Arrays.copyOfRange(base64Array, 5, base64Array.length);
byte [] decryptKey = Crypt32Util.cryptUnprotectData(base64Array);

Crypt32Util 依赖 jna,maven如下:

<dependency>
    <groupId>net.java.dev.jna</groupId>
        <artifactId>jna-platform</artifactId>
    <version>5.5.0</version>
</dependency>

3. 解密cookie值

byte [] nonce = Arrays.copyOfRange(encrypted_value,3,15);
byte [] cipherText = Arrays.copyOfRange(encrypted_value,15,encrypted_value.length);
Cipher  cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(decryptKey, "AES");
GCMParameterSpec ivSpec = new GCMParameterSpec(128,nonce);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
System.out.println(new String(cipher.doFinal(cipherText)));
Instagram 模拟登录
Jackson LocalDateTime的序列化