3

javax.crypto を使用して Java で AES CBC 復号化を行っています。次の Cipher クラス メソッドを使用しています。

  • public final void init (int opmode, Key key, AlgorithmParameters params)初期化の方法、
  • final int update(byte[] input, int inputOffset, int inputLen, byte[] output)データを復号化する方法、
  • 最後に、メソッドを呼び出してfinal int doFinal(byte[] output, int outputOffset)復号化を完了します。

私の質問は次のとおりです:doFinal呼び出しによって返されるデータのサイズが常に AES ブロック サイズ以下であると仮定できますか? ドキュメントでは、doFinal メソッドを次のように説明しています。

「マルチパート変換 (暗号化または復号化) を終了します。以前の更新呼び出しでバッファリングされた可能性のあるバイトを処理します。最終的に変換されたバイトは、出力バッファーに格納されます。」</p>

しかし、出力バッファに最大で 1 ブロックのデータが含まれるとはどこにも書かれていません。これが AES API の一般的な動作であることは理解していますが、これは私のコードがこれまで示してきた動作ですが、この仮定は常に成り立つのでしょうか?

4

2 に答える 2

3

In general (as in, in the context of the Cipher class) I don't believe it would be safe to assume this. As per the javadocs for that doFinal method:

If the output buffer is too small to hold the result, a ShortBufferException is thrown. In this case, repeat this call with a larger output buffer. Use getOutputSize to determine how big the output buffer should be.

So if you're allocating the output buffer "near" the point where you call the doFinal method, then it would make sense to call getOutputSize and allocate an appropriately-sized buffer. Job done.

On the other hand, if you're passing in a buffer from "far away" that was created to be exactly the block size, you might be in more trouble. It would be perfectly legal (at least, according to the public interface of the Java class) for a Cipher implementation to return an output larger than the block size, so long as the getOutputSize method returns the appropriate size.

In fact, if you're doing CBC decryption, doesn't that require you to pass in all of the blocks to the update method? In which case, you should get the full plaintext output back from doFinal, not just a single block?

于 2010-08-13T10:26:37.550 に答える
0

一般的に言えば、バッファリングが 1 つのブロックのみであると想定するのは安全ではありません。詳細を見ると、パディングの種類に依存していることがわかります。通常の「PKCS#5」パディングでは、少なくとも 1 バイト、最大でnバイト (サイズnのブロックの場合) が追加されるため、復号化システムはnバイトのバッファリングに制限される場合があります。他のタイプのパディングはもう少し複雑です。たとえば、CTS2nバイトのバッファリングを必要とします。Java 暗号化レイヤーは現在 CTS をサポートしていないようですが、これは将来のバージョンで追加される可能性があります。

Cipher.getOutputSize(len)len追加の入力バイトを指定すると、最大出力サイズが得られます。返される値は、実際に返される値よりも多少大きくなる可能性があります。特に復号化の場合は、復号化時に実際に検出されるパディング バイトに依存するためです。

復号化されたメッセージの合計長は、暗号化されたメッセージの合計長よりも長くないと想定しても安全です (対称暗号化にはデータ圧縮は含まれません)。したがって、入力データ バイト (暗号化されたブロック) 用と取得した出力データ バイト用の 2 つのカウンターを維持できます。差は、 から取得できるものの最大境界になりますdoFinal()。しかし、それgetOutputSize()はとにかく行うことです。

于 2010-08-13T12:19:11.830 に答える