1

3des-encryption-decryption-in-java のようなコードを使用していますが、復号化を使用すると、このようなエラーが発生しました

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
07-17 11:27:27.580: WARN/System.err(22432): at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:705)
07-17 11:27:27.580: WARN/System.err(22432): at javax.crypto.Cipher.doFinal(Cipher.java:1111)

しかし、に変更final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");するfinal Cipher decipher = Cipher.getInstance("DESede/CFB/NoPadding");と、メソッドは実行できますが、間違った結果が得られます (モードはサーバーとは異なります)。なので、その理由が知りたいです。

復号化方法:

public static String decrypt(byte[] message) throws Exception {
    final MessageDigest md = MessageDigest.getInstance("SHA-1");
    final byte[] digestOfPassword = md.digest(token.getBytes("utf-8"));
    final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
    for (int j = 0, k = 16; j < 8;) {
        keyBytes[k++] = keyBytes[j++];
    }

    final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
    final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
    final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    // final Cipher decipher = Cipher.getInstance("DESede/CFB/NoPadding");
    decipher.init(Cipher.DECRYPT_MODE, key, iv);
    final byte[] plainText = decipher.doFinal(message);
    return new String(plainText, "UTF-8");
}

暗号化方法:

public static byte[] encrypt(String message) throws Exception {
        final MessageDigest md = MessageDigest.getInstance("SHA-1");
        final byte[] digestOfPassword = md.digest(token
                .getBytes("utf-8"));
        final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        for (int j = 0, k = 16; j < 8; ) {
            keyBytes[k++] = keyBytes[j++];
        }

        final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv, new SecureRandom(new byte[5]));
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);

        final byte[] plainTextBytes = message.getBytes("utf-8");
        final byte[] cipherText = cipher.doFinal(plainTextBytes);
        return cipherText;
    }
4

1 に答える 1

1

多くの可能性があります
最も一般的なのは、特に文字エンコーディングを指定せずに、キーを文字列としてエンコードする場合です。binaryこれを行う場合は、文字エンコーディングではなく、任意のデータをエンコードするように設計された Base-64 を使用してください。
また、ソース プラットフォームとターゲット プラットフォームのエンコーディングが同じであることを確認してくださいUTF-8。 、UTF-8使用する必要があります コードが復号化中に実行されているが実行されていない

ことを伝えている事実を見てください。暗号化時に選択したパディングサイズモードを 知っておく必要があります。使用するfinal Cipher decipher = Cipher.getInstance("DESede/CFB/NoPadding");final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
CBCモードよりも例外をスローしますが、変更すると実行CFBできるようになりました。この場合、暗号化時に使用しているモードを確認する必要があります。

補足として、 CBC、OFB、および CFB は同じですが、OFB/CFB の方が優れています。暗号化のみが必要で、復号化は必要ないため、コード スペースを節約できます。
CBC(暗号ブロック連鎖)データが AES 関数を通過する場所で使用され、フィードバックが適用されて事前に暗号化されたデータが変更されるため、平文のデータが繰り返されても同じ暗号化されたデータが生成されません。データは、基礎となる暗号化機能のブロック サイズ (つまり、AES の場合は 128 ビット ブロック) に一致するブロックでのみ処理できます。このブロック レベルでの同期は、暗号化エンジンと復号化エンジンの間で提供する必要があります。判読不能
CFB(暗号フィードバックモード)これも共通モードであり、基礎となるブロック暗号をストリーム暗号のように機能させる可能性を提供します。すなわち。これにより、処理されるデータは、はるかに大きなブロックとしてのみ処理されるのではなく、短い値 (たとえば、バイトまたは個々のビットなど) のストリームになることができます。CFB モードでは、データ自体は AES エンジンを通過せず、XOR されます。 AES エンジンが以前のメッセージ履歴から生成した値を使用します。これは、データに適用される唯一の処理が XOR 関数であるため、CFB 関数によるレイテンシを最小限に抑えることができることを意味します。データ幅は、基礎となる暗号ブロック サイズまでの任意のサイズに設定できますが、データ幅とブロック サイズの比率で幅が小さくなると、スループットが低下することに注意してください。 (補足:D)
Cipher-Feedback (CFB) または Output-Feedback (OFB) または counter (CTR) モードを使用して暗号化する場合、暗号文は平文と同じサイズになるため、パディングは必要ありません。ただし、初期化ベクトル (IV) は一意でなければならないため、これらのモードを使用する場合は注意してください。
同様に、RC4 や PC1 などのストリーム暗号を使用した暗号化では、パディングは必要ありません。

ここで、ブロック サイズとパディング サイズに注意するよりもさらに批判的に調査する場合 (既に上記で説明しました)。最初に確認する必要があるのは、暗号化アルゴリズムによって定義されたパディング サイズです。CFB で述べたようにケースのパディングは必要ないので、最初はパディングなしで試してください。問題が解決しない場合は、問題があるか
どうかを確認してくださいpkcs5pkcs7.decrytpion パディング サイズを に設定して、コードを試してくださいpkcs7。そうでpkcs7あれば、CBC でも動作するはずです。追加情報として、Using Padding in Encryptionを読むことをお勧めします。


  • PKCS#5 パディングは RFC 2898 (PKCS #5: Password-Based Cryptography Specification Version 2.0) で定義されています。

  • PKCS5 パディングは、受信側が確実にパディングを削除できるように、ブロック暗号のブロックサイズに一致するように任意のデータを拡張するためのパディング スキームです。

  • PKCS#7 (CMS、RFC 3369) はパディング スキームを定義しますが、これは、ブロックに 8 バイトを超えるブロック暗号の PKCS#5 パディングの拡張です。

于 2013-07-17T04:03:53.197 に答える