如何使用 Python 将 SQLite Blob 字段转换为字符串

How to convert SQLite Blob field to string with Python

我想打开 Chrome(登录数据)文件并使用其密码字段。但是这个字段是以byte/blob方式存储的,不能转成文本

我也尝试了 codecs 和 pickle 以及 bytes.encode 和 str.decode 但它没有用。 请查看下面的代码并提供帮助:

import sqlite3

connection_obj = sqlite3.connect('C:/Users/{username}/AppData/Local/Google/Chrome/User 
Data/Default/Login Data')

cursor_obj = connection_obj.cursor()

statement = '''SELECT action_url, username_value, password_value  FROM logins'''

cursor_obj.execute(statement)

output = cursor_obj.fetchmany(5)

for url,usr,psw in output:
     # convert psw blob -> ascii text
     # ....
     # ....
     # for example psw filed:
     # b'v10\x7f\xa3\x1a\xd1\x83g\x8c\xc4\x14]\xb6n\xf85\xba\xca\xf5r\x17\xb6D\xed\xf5\x11rM\xbe\xbf\xb1\xc2y\xc5Vr\xc3\xb3NB\xc7J\x14\x95'
     # 
     # convert to below text : 
     # zarfilm-136342

   print(url, usr, psw,sep='------') 
   print('*'*10)

connection_obj.commit()
connection_obj.close()

得知此字段已加密,您感到惊讶吗?如果不是,Google 将会陷入麻烦的世界。甚至 Chrome 也不知道如何解密。它是通过 Windows 加密 API 完成的,并且涉及到您的 Windows 登录密码。你无法得到它们。

该数据在 AES 中加密,并且进一步使用 CryptProtectData 加密密钥以将加密密钥锁定到用户数据。你可以用这样的东西解密数据:

import base64, json, os, sqlite3, win32crypt
from Crypto.Cipher import AES

def chrome_key():
    local_state_fn = os.path.join(os.environ["USERPROFILE"],"AppData","Local","Google","Chrome","User Data","Local State")
    with open(local_state_fn, "r") as f:
        local_state = json.load(f)
    key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
    key = key[5:]
    return win32crypt.CryptUnprotectData(key, None, None, None, 0)[1]

def decrypt_password(password, key):
    iv, password = password[3:15], password[15:]
    aes = AES.new(key, AES.MODE_GCM, iv)
    return aes.decrypt(password)[:-16].decode("utf-8")

def main():
    key = chrome_key()
    db_fn = os.path.join(os.environ["USERPROFILE"],"AppData","Local","Google","Chrome","User Data","default","Login Data")
    db = sqlite3.connect(db_fn)
    for origin_url, username, password_crypt in db.execute("SELECT origin_url, username_value, password_value FROM logins;"):
        password = decrypt_password(password_crypt, key)
        print(f"{origin_url}, {username}, {password}")
    db.close()

if __name__ == "__main__":
    main()