[Python]keepass v1 DB ツール
keepassというパスワード保存ツールがあります。Windows/Linux/Mac/Androidと幅広いプラットフォームで使えるのが魅力です。
これのLinux版はkeepassxという名前であるのですが、ビルドにはQTが必要で、ターミナルからは使えません。というわけで、ターミナルから使えるツールが欲しいな、と思い、調査と実装をしてみました。
ヘッダの構造
ヘッダは124byte。
0123 4567 89AB CDEF 0123 4567 89AB CDEF
+----+----+----+----+---------+----+----+
|sig1|sig2|flag|ver | seed_rand |
+----+----+----+----+----+----+----+----+
| encription IV |gron|entn|checksum |
+----+----+----+----+----+----+----+----+
| check_sum (cont) |seed_key |
+----+----+----+----+----+----+----+----+
| seed_key (cont) |seed_rotn|
+----+----+----+----+----+----+----+----+
- gron * group number
- entn * entity number
- seed_rotn * seed rot number
Python的なunpackで書くとこんな感じ。
format = '<L L L L 16s 16s L L 32s 32s L'
Signature 1 は0x9AA2D903 で、Signature 2 は 0xB54BFB65 。
flagsは * DB_FLAG_SHA2 = 1 * DB_FLAG_RIJNDAEL = 2 * DB_FLAG_ARCFOUR = 4 * DB_FLAG_TWOFISH = 8
Decrypt
decryptはこんな感じで行われます。
# headerをparse
header = parse_db(buffer)
# masterpassをsha256
key = hashlib.sha256(masterpass).digest()
# seed_keyを使ってECBモードなAESを作成
cipher = AES.new(header.seed_key, AES.MODE_ECB)
# seed_rot_n回 keyをAESでencrypt
for i in range(1, self.header.seed_rot_n):
key = self.cipher.encrypt(key)
# keyをsha256
finalkey = hashlib.sha256(key).digest()
# headerのencription ivを使ってCBCモードなAESを作成
cipher = AES.new(finalkey, AES.MODE_CBC, header.enc_iv)
# 複号
buf = cipher.decrypt(buf)
# 最後の一文字の文字コードを取得
extra = ord(buf[-1])
# その文字コードの数分だけ削る
buf = buf[:len(buf)-extra] # last len(extra) becomes blank
groupとentry
decryptしたあとは、groupとentryの情報を読み出して行きます。
これは、 * type: 2byte * length: 4byte * value: length分 という構造になります。
typeの詳細はここでは省きますが、typeが0xFFFFがgroupとentryの終わりになります。これを、headerにある、n_groupsとn_entriesの数だけ繰り返します。
source
という辺りを実装したものをgithubに上げておきました。
http://github.com/shirou/kptool
まだDBへの書き出しなどは実装していませんが、自分的にはこれで十分だったりします。