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への書き出しなどは実装していませんが、自分的にはこれで十分だったりします。
参考文献
- keepassx
- CPAN File::KeePass