簡體   English   中英

雙重加密/解密失敗,但單一加密/解密失敗-AES 256位

[英]Double encryption / decryption fails but single does not - AES 256 bit

因此,這種特殊情況非常普遍,但是我的問題與通常提出的問題略有不同。

我已經定義了AES解密和加密功能,如下所示:

    public static byte[] encrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
            throws java.io.UnsupportedEncodingException,
            NoSuchAlgorithmException,
            NoSuchPaddingException,
            InvalidKeyException,
            InvalidAlgorithmParameterException,
            IllegalBlockSizeException,
            BadPaddingException {

        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher;
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
        return cipher.doFinal(textBytes);
    }

    public static byte[] decrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
            throws java.io.UnsupportedEncodingException,
            NoSuchAlgorithmException,
            NoSuchPaddingException,
            InvalidKeyException,
            InvalidAlgorithmParameterException,
            IllegalBlockSizeException,
            BadPaddingException {

        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
        return cipher.doFinal(textBytes);
    }

現在,如果我像這樣執行一次解密:

System.out.println(Arrays.toString(
                AES256Cipher.decrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(aKeys[a]),
                        AES256Cipher.encrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(aKeys[a]),
                                AES256Cipher.encrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(bKeys[b]), HexBytePlainWriter.hexStringToByteArray(zkeys[a^b]))
                                )
                        )));

字節數組輸出就可以了。 而如果我執行雙重加密/解密:

        System.out.println("dec: " + HexBytePlainWriter.ByteToHexString(
            AES256Cipher.decrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(aKeys[a]),
                    AES256Cipher.decrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(bKeys[b]),
                            AES256Cipher.encrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(aKeys[a]),
                                    AES256Cipher.encrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(bKeys[b]), HexBytePlainWriter.hexStringToByteArray(zkeys[a^b]))
                                    )
                            ))));

我得到了著名的javax.crypto.BadPaddingException: Given final block not properly padded Exception。 請注意, ab只是整數(假設它們都為0)。 當前,IVBytes只是一個大小為16的空字節數組,用new byte[16] aKeysbKeys都是帶有AES加密(隨機)字符串(長度為32個字節)的String數組。

這些是我使用的輔助函數(將byte []轉換為十六進制字符串,反之亦然):

public static  String ByteToHexString (byte[] data) {
        StringBuilder buf = new StringBuilder();
        for (byte b : data) {
            int halfbyte = (b >>> 4) & 0x0F;
            int two_halfs = 0;
            do {
                buf.append((0 <= halfbyte) && (halfbyte <= 9) ? (char) ('0' + halfbyte) : (char) ('a' + (halfbyte - 10)));
                halfbyte = b & 0x0F;
            } while (two_halfs++ < 1);
        }
        return buf.toString();
    }

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                                 + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

我懷疑第一次解密的​​輸出會使密文格式錯誤,以至於外部會引發異常。 我檢查了大小,外部部分輸出了32個字節,因此應該可以。 這不符合PKC5Padding嗎?

任何幫助深表感謝。

編輯:

看來我的最小示例是錯誤的:我首先使用鍵B而不是A。但是Jon Skeet確實給了我一個主意。 如果我有什么新東西,我會編輯。

編輯2:

這個想法是正確的。 我正在遍歷一個亂碼的真值表(對於那些感興趣的人,請查看Wikipedia文章 )並檢查所有可能的密文(CT)。 問題是,如果您選擇了不正確的CT並對其進行了雙重解密,則它將拋出異常,因為第一次解密會返回垃圾。 只需檢查表中的鍵即可解決此問題。

您使用錯誤的密鑰進行解密。 您正在使用密鑰B加密,然后使用密鑰A加密結果。然后嘗試使用密鑰B解密結果,並使用密鑰A解密最終結果。

每次解密時,都應指定用於執行“最新”加密操作的相同密鑰。 所以:

         Encrypt         Encrypt        Decrypt        Decrypt
         with B          with A         with A         with B
Plain text -> encrypted I -> encrypted II -> encrypted I -> plain text

我還建議,在同一時間執行這些操作的一個聲明,而不是從往上由於在單個語句做的一切閱讀,就會使人們更方便明白發生了什么事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM