openssl で AES 暗号化したファイルを java で復号
2018/09/20 - moriya - ~3 Minutes
android で暗号化したファイルを復号しようと思ったが、どのようにするか。
暗号化は、わざわざツールを作るのも面倒なので、openssl でよいかと考えた。
openssl java で検索すると以下のような記事が見つかる。
openssl enc -e -aes-128-cbc で暗号化したファイルの先頭には、Salted__ソルトが入るようだ。
これは、openssl の仕様で、Java の Cipher クラスには、そのようなインタフェースはない。
上記の記事ではそれらを実装しているのだと思うが、面倒だし、openssl 依存というのもなあ、と思った。
とりあえず、man enc してみた。たぶん、そうこうしている間に実装できただろうが。
興味深いオプションとしては、-P オプション、-S オプション、-nosalt オプション、-K、-iv オプションだろうか。
オプション | 機能 |
---|---|
-P オプション | salt、key、iv を表示して終了する。 |
-S オプション | salt を指定して暗号化する。 |
-nosalt | salt を使わない。 |
-K、-iv | -K で指定したキーと -iv で指定した initial vector を使う。 |
暗号化する時に、Key / iv を表示させて、それを Java の Cipher クラスに渡せばよい。
使用例:
$ openssl enc -aes-128-cbc -P
enter aes-128-cbc encryption password:
Verifying - enter aes-128-cbc encryption password:
salt=E89360B042EFDBE0
key=35E38573AB84F2054BB8BCD8E5CD56EE
iv =382EA02910F2C2B5E2990846A30C169D
パスワードは hogehoge を入れてみた。実行毎に salt は変わるので、key/iv は変わる。もし、同じ salt を指定したければ、次のとおり。
$ openssl enc -aes-128-cbc -P -S E89360B042EFDBE0
enter aes-128-cbc encryption password:
Verifying - enter aes-128-cbc encryption password:
salt=E89360B042EFDBE0
key=35E38573AB84F2054BB8BCD8E5CD56EE
iv =382EA02910F2C2B5E2990846A30C169D
試しに salt を指定して暗号化したファイルの hexdump。
$ openssl enc -aes-128-cbc -S E89360B042EFDBE0 -in hoge.txt -out hoge.txt.enc
$ hexdump -C hoge.txt.enc
00000000 53 61 6c 74 65 64 5f 5f e8 93 60 b0 42 ef db e0 |Salted__..`.B...|
00000010 65 f6 60 7a 8f f7 e3 21 a3 b2 dd a1 5c a7 dd be |e.`z...!....\...|
00000020
(-nosalt を使えば、Salted__ソルト、は出力されない。)
もらったファイルから key / iv を表示する場合
$ openssl enc -d -aes-128-cbc -in hoge.txt.enc -P
enter aes-128-cbc decryption password:
salt=E89360B042EFDBE0
key=35E38573AB84F2054BB8BCD8E5CD56EE
iv =382EA02910F2C2B5E2990846A30C169D
ソルトの部分を削れば復号できるのか。
$ dd if=hoge.txt.enc of=hoge.txt.enc.nosalt bs=1 skip=16
16+0 records in
16+0 records out
16 bytes transferred in 0.000732 secs (21860 bytes/sec)
$ hexdump -C hoge.txt.enc.nosalt
00000000 65 f6 60 7a 8f f7 e3 21 a3 b2 dd a1 5c a7 dd be |e.`z...!....\...|
00000010
$ openssl enc -d -aes-128-cbc -in hoge.txt.enc.nosalt -K 35E38573AB84F2054BB8BCD8E5CD56EE -iv 382EA02910F2C2B5E2990846A30C169D
$ openssl enc -d -aes-128-cbc -in hoge.txt.enc.nosalt -K 35E38573AB84F2054BB8BCD8E5CD56EE -iv 382EA02910F2C2B5E2990846A30C169D
hogehoge
Java Cipher を使って復号する場合
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); // openssl は PKCS5Padding で暗号化する
Key k = new SecretKeySpec(key, "AES"); // key は byte 配列
IvParameterSpec p = new IvParameterSpec(iv); // iv は byte 配列
c.init(Cipher.DECRYPT_MODE, k, p);
byte[] ret = c.doFinal(buf); // buf は byte 配列 (Salted__ソルトは削るか-nosaltで出力させない)
[PR]
私は、「Java チュートリアル」という本でざっくりと使い方を習得しました。内容も古くなっているため、Amazon おすすめの本を購入するのが良いと思います。 Java を習得する必要があるのに、間違って JavaScript の本を買わないように。