androidアプリ診断をしていると「Cipher.getInstanceを使用している場合、安全な暗号を明示的に指定しているか」と確認することがあります。
文書的にはデフォルトで安全でないモードが使用されるからだそうですが、その挙動を見たことが無いので確かめてみました。
参考暗号化ロジック

とりあえずいじる
まずは「”AES”」指定でやります。

参考プログラムの暗号化ロジックをそのままにしていたら例外が発生しました。
ECBモードではIV(初期化ベクトル)は使えないそうです。

とりあえずいろいろ暗号化する
この時点でECBモードだということがわかりましたが、「test」という文字列を以下のアルゴリズムで暗号化してbase64してみようと思います。
- AES
- AES/CBC/PKCS5Padding
- AES/ECB/PKCS5Padding
鍵は「nick123456789012」、初期化ベクトルはなしでいきます。
AES
uyN/gSYIUYMK6ZTIjQxSwA==
AES/CBC/PKCS5Padding(復号に失敗していました)
qzqaRJlqsgQNmAKaoGp7Rw==
AES/ECB/PKCS5Padding
uyN/gSYIUYMK6ZTIjQxSwA==
AESは「AES/ECB/PKCS5Padding」っぽいですね。
結論
Cipher.getInstanceに「AES」を指定すると「AES/ECB/PKCS5Padding」が使用される。
ECBモードは安全ではないので使用しないこと。
ECB暗号テキストは同じプレーン・テキスト/キーを使用する場合は同一になるため、このモードは、通常は暗号化アプリケーションに適していません。使用しないようにしてください。
Java暗号化アーキテクチャ(JCA)リファレンス・ガイド Cipherクラス-操作モード https://docs.oracle.com/javase/jp/11/security/java-cryptography-architecture-jca-reference-guide.html#GUID-94225C88-F2F1-44D1-A781-1DD9D5094566
終わりに
AESを指定するとデフォルトで何が使用されるかの検証でした。
このあたりの仕様、優しくないです。
検証が終わった後にググったらもっと細かい検証記事が見つかりました。
もっと早く見つけられたら・・・と思いましたが、検証したからこそこの記事の内容も理解できたのではと思いました(そう思わないとやってられないです)
Javaの暗号化アーキテクチャのドキュメントも(上記記事のおかげで)見つかったので今回の検証から得られることは多かったなと思いました。
コメント