OSXでKeePassXの鍵をコマンドライン1発で取得するまでの手順


GUIが使えない環境などでKeePassXの鍵を取得したいなと思い立ち、挑戦してみました。

## kptoolの導入

検索すると [Command Line で使用しているツールまとめ vol.2](http://qiita.com/PSP_T/items/8fab37433f8b9606f75c) がすぐ出てきます。
Pythonでkptoolを動かすための環境を整えます。

[GitHub shirou/kptool](https://github.com/shirou/kptool)

```bash
$ git clone https://github.com/shirou/kptool.git
$ python kptool/kptool/kptool.py path/to/kdbfile
Traceback (most recent call last):
  File "kptool/kptool/kptool.py", line 9, in <module>
    from keepassdb import keepassdb
  File "/Users/east/git/kptool/kptool/keepassdb/keepassdb.py", line 6, in <module>
    from Crypto.Cipher import AES
ImportError: No module named Crypto.Cipher
```

早速 Cryptoが無いよと言われました。pipでインストールします。
 
```bash
$ pip install pycrypto 
-bash: pip: command not found
```

pipも無いよと言われました。pipをインストールします。

```bash
$ sudo easy_install pip
Searching for pip
Reading http://pypi.python.org/simple/pip/
Best match: pip 1.5.4
Downloading https://pypi.python.org/packages/source/p/pip/pip-1.5.4.tar.gz#md5=834b2904f92d46aaa333267fb1c922bb
Processing pip-1.5.4.tar.gz
Running pip-1.5.4/setup.py -q bdist_egg --dist-dir /tmp/easy_install-8UYX4X/pip-1.5.4/egg-dist-tmp-HXMDdl
warning: no files found matching 'pip/cacert.pem'
warning: no files found matching '*.html' under directory 'docs'
warning: no previously-included files matching '*.rst' found under directory 'docs/_build'
no previously-included directories found matching 'docs/_build/_sources'
Adding pip 1.5.4 to easy-install.pth file
Installing pip script to /usr/local/bin
Installing pip2.7 script to /usr/local/bin
Installing pip2 script to /usr/local/bin
 
Installed /Library/Python/2.7/site-packages/pip-1.5.4-py2.7.egg
Processing dependencies for pip
Finished processing dependencies for pip
```

pipのインストールが完了。

```bash
$ pip install pycrypto
Command /usr/bin/python -c "import setuptools, tokenize;__file__='/private/var/folders/47/lrzh0xp935z2ppgpth8cx44w0000gn/T/pip_build_east/pycrypto/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /var/folders/47/lrzh0xp935z2ppgpth8cx44w0000gn/T/pip-4slDJi-record/install-record.txt --single-version-externally-managed --compile failed with error code 1 in /private/var/folders/47/lrzh0xp935z2ppgpth8cx44w0000gn/T/pip_build_east/pycrypto
Storing debug log for failure in /Users/east/Library/Logs/pip.log
```

なんか赤文字でエラーになりました。sudoで実行します。

```bash
$ sudo pip install pycrypto
 
Successfully installed pycrypto
Cleaning up...
```

うまくいったみたい。

```bash 
$ python kptool/kptool/kptool.py path/to/kdbfile
Enter password ['path/to/kdbfile']
Password: 
kptool> list
```

listで該当kdbに保存されているエントリーのタイトル一覧が出てくれば成功です。

## kptoolを改造

1発で取得したかったのでkptoolをコピペ改造しました。

```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import argparse
import getpass
import datetime
import readline
 
from keepassdb import keepassdb
 
if __name__ == '__main__':
 
  parser = argparse.ArgumentParser(description='search entry from keepass DB')
  parser.add_argument('kdb_file',
                      nargs=1,
                      help = 'keepass DB file path')
  parser.add_argument('title',
                      nargs=1,
                      help = 'entry title')
  parser.add_argument('-p', '--password')
 
  args = parser.parse_args()
 
  if (not args.password):
    password = getpass.getpass()
  else:
    password = args.password
 
  try:
    k = keepassdb.KeepassDBv1(args.kdb_file[0], password)
  except ValueError:
    print("Invalid password.")
    exit(1)
 
  for e in k.get_entries():
    title = e['title'].encode('utf-8')
    if (title == args.title[0]):
      print("id:%s" % e['id'].encode('utf-8'))
      print("title:%s" % title)
      print("url:%s" % e['url'].encode('utf-8'))
      print("username:%s" % e['username'].encode('utf-8'))
      print("password:%s" % e['password'].encode('utf-8'))
```

できた！！

-p オプションでパスワードを付与するとそのパスワードを使用。
-p オプションが無い場合はプロンプトでパスワード入力を促す。
適当に必要そうなデータをprintしています。

## コマンドラインから鍵を取得

```bash
#!/bin/sh

KEEPASS_SCRIPT=~/git/kptool/kptool/getentry.py
LOCAL_KDB_FILE=path/to/kdbfile
LOCAL_KDB_ENTRY=欲しい鍵のタイトル

HOGE_PASSWORD=`python ${KEEPASS_SCRIPT} ${LOCAL_KDB_FILE} ${LOCAL_KDB_ENTRY} | grep password | cut -d ':' -f 2`
echo $KEEPASS_SCRIPT
```

こんな感じのシェルスクリプトを書いておくとパスワードを入力するだけで簡単に取得できます。
ここではechoしていますが、パスワードをechoするのはあまり正しい運用ではないと思うのでご注意。
適切なプログラムに組み込んだりして使うといい感じです。


## さらに...

kdbファイルが別のkdbファイルの2次連携になっている場合など、
-pオプションが効果を発揮します。

```bash
#!/bin/sh

KEEPASS_SCRIPT=~/git/kptool/kptool/test.py
LOCAL_KDB_FILE=path/to/kdbfile
LOCAL_KDB_ENTRY=欲しい1次鍵のタイトル
APP_KDB_FILE="$1"
APP_KDB_ENTRY='HogeApp (hoge) hogehoge'

if [ -z $APP_KDB_FILE ]
then
  echo "Usage: $0 path/to/app.kdb"
  exit 1
fi

APP_KDB_PASSWORD=`python ${KEEPASS_SCRIPT} ${LOCAL_KDB_FILE} ${LOCAL_KDB_ENTRY} | grep password | cut -d ':' -f 2`
APP_URL=`python ${KEEPASS_SCRIPT} ${APP_KDB_FILE} "${APP_KDB_ENTRY}" -p ${APP_KDB_PASSWORD} | grep url | head -n 1 |cut -d ':' -f 2`
APP_PASSWORD=`python ${KEEPASS_SCRIPT} ${APP_KDB_FILE} "${APP_KDB_ENTRY}" -p ${APP_KDB_PASSWORD} | grep password | head -n 1 |cut -d ':' -f 2`
```

1次鍵の入力だけで簡単にデータを取得できて効率アップ！
必要最低限のパスワードの入力だけで動作する環境を構築できました。

まさに心境は [カチャカチャカチャ・・・ッターン！](http://jigokuno.com/?eid=306)

おしまい