ファイルの AES 暗号化/復号化を行う Android アプリを作成しています。間違ったパスワードが指定されているかどうかを検出できるようにしたいため、一致しないキーが復号化のために導出されます。256 ビット キーで AES/CBC/PKCS7Padding を使用しています。cipher.doFinal() を実行すると、BadPaddingException を試行/キャッチでき、何かが間違っていて、おそらくキーが間違っていることがわかります。しかし、CipherInputStream を使用して暗号化されたファイルを読み取ると、パディングの正確性に関するフィードバックが得られません。したがって、意図的に間違ったパスワードを指定すると、ファイルが復号化され、すべてが正常であると報告されますが、復号化されたファイルは完全にジャンクです。だから私の質問は、CipherInputStream を使用するときに悪いパディングを検出する方法ですか?
6 に答える
既知のヘッダーをデータの先頭に追加します。最初に復号化し、期待したものと一致しない場合は停止してエラーを返します。
代わりに GCM モードを使用してみてください (Java 7 または Bouncy Castle プロバイダー)。パディングの秘訣は、メッセージが変更された後 (約 256 回に 1 回) 正しい場合があることです。GCM モードでは相互保護が追加されるため、変更を加えると、BadPaddingException から派生した例外が発生します。
ただし、GCM で暗号化するときは (ランダムな) ナンスを先頭に追加する必要があります (実際には CBC モードのルールでもありますが、CBC でランダムでない IV を使用することの影響はそれほど深刻ではありません)。
badpaddingexception を取得するには最終的な計算を実行する必要があることに注意してください。そのため、基になるストリームを閉じるか終了することを忘れないでください。これはおそらくあなたの現在の問題です。
[編集]:これは答えではありませんが、入力を使用してより良いを生成できます。この質問に関する他の回答CipherInputStream
を参照してください。
これは、CipherInputStream の getMoreData() メソッドの修正版です。これは、私の問題に直面した人にとって役立つかもしれません。
private int getMoreData() throws IOException {
if (done) return -1;
int readin = input.read(ibuffer);
if (readin == -1) {
done = true;
try {
obuffer = cipher.doFinal();
}
catch (IllegalBlockSizeException e) {
throw new IOException(e);
}
catch (BadPaddingException e) {
throw new IOException(e);
}
if (obuffer == null)
return -1;
else {
ostart = 0;
ofinish = obuffer.length;
return ofinish;
}
}
try {
obuffer = cipher.update(ibuffer, 0, readin);
} catch (IllegalStateException e) {obuffer = null;};
ostart = 0;
if (obuffer == null)
ofinish = 0;
else ofinish = obuffer.length;
return ofinish;
}
何らかの理由で悪いパディングがキャッチされたと思います。これはCipherInputStream
ソースからのものです:
private int getMoreData() throws IOException {
if (done) return -1;
int readin = input.read(ibuffer);
if (readin == -1) {
done = true;
try {
obuffer = cipher.doFinal();
}
catch (IllegalBlockSizeException e) {obuffer = null;}
catch (BadPaddingException e) {obuffer = null;}
if (obuffer == null)
return -1;
else {
ostart = 0;
ofinish = obuffer.length;
return ofinish;
}
}
try {
obuffer = cipher.update(ibuffer, 0, readin);
} catch (IllegalStateException e) {obuffer = null;};
ostart = 0;
if (obuffer == null)
ofinish = 0;
else ofinish = obuffer.length;
return ofinish;
}