1

BlackBerryのデータをAES形式で正常に暗号化しました。結果を確認するために、次の方法を使用してBlackBerryに復号化を実装しようとしています。

 private static byte[] decrypt( byte[] keyData, byte[] ciphertext )throws CryptoException, IOException
{
   // First, create the AESKey again.
   AESKey key = new AESKey( keyData );

   // Now, create the decryptor engine.
   AESDecryptorEngine engine = new AESDecryptorEngine( key );
   // Since we cannot guarantee that the data will be of an equal block length
   // we want to use a padding engine (PKCS5 in this case).
   PKCS5UnformatterEngine uengine = new PKCS5UnformatterEngine( engine );

   // Create the BlockDecryptor to hide the decryption details away.
   ByteArrayInputStream input = new ByteArrayInputStream( ciphertext );
   BlockDecryptor decryptor = new BlockDecryptor( uengine, input );

   // Now, read in the data. Remember that the last 20 bytes represent
   // the SHA1 hash of the decrypted data.
   byte[] temp = new byte[ 100 ];
   DataBuffer buffer = new DataBuffer();

   for( ;; ) {
       int bytesRead = decryptor.read( temp );
       buffer.write( temp, 0, bytesRead );

       if( bytesRead < 100 ) {
           // We ran out of data.
           break;
       }
   }

   byte[] plaintextAndHash = buffer.getArray();
   int plaintextLength = plaintextAndHash.length - SHA1Digest.DIGEST_LENGTH;
   byte[] plaintext = new byte[ plaintextLength ];
   byte[] hash = new byte[ SHA1Digest.DIGEST_LENGTH ];

   System.arraycopy( plaintextAndHash, 0, plaintext, 0, plaintextLength );
   System.arraycopy( plaintextAndHash, plaintextLength, hash, 0,
       SHA1Digest.DIGEST_LENGTH );

   // Now, hash the plaintext and compare against the hash
   // that we found in the decrypted data.
   SHA1Digest digest = new SHA1Digest();
   digest.update( plaintext );
   byte[] hash2 = digest.getDigest();

   if( !Arrays.equals( hash, hash2 )) {
       throw new RuntimeException();
   }

   return plaintext;
}

次の行で「BadPaddingException」がスローされた例外が発生します

int bytesRead = decryptor.read( temp );

誰か助けてくれませんか。

4

3 に答える 3

2

問題はこのブロックにあると思います:

    for( ;; ) {
       int bytesRead = decryptor.read( temp );
       buffer.write( temp, 0, bytesRead );

       if( bytesRead < 100 ) {
           // We ran out of data.
           break;
       }
   }

-1を返す場合read、それもバッファに書き込んでいます。そして、終了条件も間違っています。これをCryptoDemoサンプルプロジェクトのブロックと比較してください。

    for( ;; ) {
        int bytesRead = decryptor.read( temp );

        if( bytesRead <= 0 )
        {
            // We have run out of information to read, bail out of loop
            break;
        }

        db.write(temp, 0, bytesRead);
     }

また、エラーの原因ではない場合でも、注意が必要な点がいくつかあります。

    AESDecryptorEngine engine = new AESDecryptorEngine( key );

このコンストラクターのドキュメントを読むと、次のようになります。

「デフォルトのブロック長が16バイトのAESキーを指定して、AESEncryptorEngineクラスのインスタンスを作成します。」

ただし、前の行では、キーを作成するときに次のことを行っています。

    AESKey key = new AESKey( keyData );

ドキュメントによると、 「既存のデータから可能な限り長いキーを作成します」。、ただし、「配列の最初の128ビットのみが使用されます」。したがって、長さは関係ありません。keyData常に128ビットのキー長を使用します。これは、使用可能な3つのサイズ(128、192、256)の中で最も短いものです。

代わりに、アルゴリズムブロックキーの長さを明示的に選択できます。たとえば、AES-256を使用するには:

AESKey key = new AESKey(keyData, 0, 256); //key length in BITS
AESDecryptorEngine engine = new AESDecryptorEngine(key, 32); //key lenth IN BYTES

最後に、これが機能する場合でも、パスワード(任意のサイズの場合があります)からキーを直接取得することは安全ではないことに注意する必要があります。パディングにPKCS5を使用する代わりに、PKCS5KDF2PseudoRandomSourceを使用して、キーマテリアル(パスワード)からより強力なキーを取得できます。

于 2013-01-16T09:22:43.793 に答える
1

暗号化されたデータは、ブロックサイズ(16バイト)に正しく埋め込まれている必要があります。パディングなしでデータを復号化して、テールバイトがPKCS#5パディングに対応するかどうかを確認します(たとえば、5バイトのパディングが必要な場合は、0x05 0x05 0x05 0x05 0x05バイトを追加する必要があります)。

于 2013-01-16T08:57:41.837 に答える
0

問題は、正しいブロックサイズのデータ​​が復号化されることです。それに関する問題は、ランダムに見えるガベージに復号化される可能性が高いことです。ランダムに見えるガベージは、PKCS#7パディングスキームと互換性がないことが多いため、例外です。

キーデータが無効な場合、間違ったパディングまたはブロックモードが使用された場合、または単に入力データがプロセス中に文字化けした場合に、この例外がスローされる可能性があるため、問題と言います。これをデバッグする最良の方法は、アルゴリズムが一致し、バイナリ入力パラメーター(APIによるデフォルトのパラメーターを含む)が両側で正確に一致することを100%確認することです。

于 2013-01-17T00:34:16.583 に答える