いろいろな場所に保管しているパスワードをうまく集中管理できないかなーと思いたち、Chromeから抽出する方法を調べた。
手段1:手動エクスポート
Googleアカウントのパスワードマネージャーからエクスポートすることができる。
手段2:プログラムでエクスポート
いろいろ調べて試行錯誤した結果、以下のようなpythonコードで抽出できた。
# 以下のライブラリに依存
# keyring
# pycryptodome
import os
import shutil
import sqlite3
from hashlib import pbkdf2_hmac
import keyring
from Crypto.Cipher import AES
def decrypt(encrypted_value):
my_pass = keyring.get_password('Chrome Safe Storage', 'Chrome')
key = pbkdf2_hmac('sha1', my_pass.encode('utf8'), salt=b'saltysalt', iterations=1003, dklen=16)
cipher = AES.new(key, AES.MODE_CBC, IV=(b' ' * 16))
decrypted = cipher.decrypt(encrypted_value[3:]) # 先頭の'v10'をカット
return bytearray(filter(lambda x: 0x1f < x, decrypted)).decode('utf-8')
chrome_path_login_db = os.path.expanduser('~/Library/Application Support/Google/Chrome/Default/Login Data')
shutil.copy2(chrome_path_login_db, "Loginvault.db")
with sqlite3.connect("Loginvault.db") as conn:
cursor = conn.cursor()
cursor.execute("SELECT origin_url, action_url, username_value, password_value FROM logins")
for login in cursor:
print(f"{login[0]}\t{login[1]}\t{login[2]}\t{decrypt(login[3])}")
付録:Chromeのパスワード管理の仕様
パスワードはここで管理されている(Macの場合)
~/Library/Application Support/Google/Chrome/Default/Login Data
パスワードファイルはsqliteでアクセスできる
loginsテーブルに格納されている
% sqlite3 "$HOME/Library/Application Support/Google/Chrome/Default/Login Data"
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
sqlite> .tables
field_info meta sync_entities_metadata
insecure_credentials password_notes sync_model_metadata
logins stats
sqlite> PRAGMA table_info(logins);
0|origin_url|VARCHAR|1||0
1|action_url|VARCHAR|0||0
2|username_element|VARCHAR|0||0
3|username_value|VARCHAR|0||0
4|password_element|VARCHAR|0||0
5|password_value|BLOB|0||0
6|submit_element|VARCHAR|0||0
7|signon_realm|VARCHAR|1||0
8|date_created|INTEGER|1||0
9|blacklisted_by_user|INTEGER|1||0
10|scheme|INTEGER|1||0
11|password_type|INTEGER|0||0
12|times_used|INTEGER|0||0
13|form_data|BLOB|0||0
14|display_name|VARCHAR|0||0
15|icon_url|VARCHAR|0||0
16|federation_url|VARCHAR|0||0
17|skip_zero_click|INTEGER|0||0
18|generation_upload_status|INTEGER|0||0
19|possible_username_pairs|BLOB|0||0
20|id|INTEGER|0||1
21|date_last_used|INTEGER|1|0|0
22|moving_blocked_for|BLOB|0||0
23|date_password_modified|INTEGER|1|0|0
password_valueは暗号化されている
Encryption Scheme: AES-128 CBC with a constant salt and constant iterations. The decryption key is a PBKDF2 key generated with the following:
Salt: The salt is ‘saltysalt’ (constant)
Iterations: 1003 (constant) for symmetric key derivation.
IV: 16 spaces.
Hashing function: sha1
Password: This is the important non-constant part. What we need is stored in the user’s keychain as “Chrome Safe Storage”. What is beautiful about this, is that we do not actually need the user’s keychain password to access this Safe Storage Key. We can directly call the macOS security process, through the command line using ‘security find-generic-password -ga Chrome’, to present the following dialog: …
https://f002.backblazeb2.com/file/sec-news-backup/files/writeup/bufferovernoah.com/2016_10_17_chrome/index.html
【参考】Chromiumのソースコード