簡體   English   中英

這種AES 128加密有什么問題?

[英]What is wrong with this AES 128 encryption?

我無法理解為什么我的密碼長於基於以下向量的預期輸出。 我不會解釋代碼,因為我覺得它非常整潔。

package mundo;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

class AESTest {
   public static void main(String[] args) throws Exception {
     //each array is a vector case {key, plainText, expectedCipher}
     String[][] cases = new String[][]{{"00000000000000000000000000000000", "f34481ec3cc627bacd5dc3fb08f273e6","0336763e966d92595a567cc9ce537f5e"},
                                       {"00000000000000000000000000000000", "9798c4640bad75c7c3227db910174e72", "a9a1631bf4996954ebc093957b234589"},
                                       {"2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"},
                                       {"2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"}};
     for(String[] kase : cases)
     {
         byte[] theKey = byte2hex(kase[0]);
         byte[] theMsg = byte2hex(kase[1]);
         byte[] theExp = byte2hex(kase[2]);
         Cipher cipher = Cipher.getInstance("AES");
         SecretKeySpec keySpec = new SecretKeySpec(theKey, "AES");
         cipher.init(Cipher.ENCRYPT_MODE, keySpec);
         byte[] cryptMsg = cipher.doFinal(theMsg);
         System.out.println("Key     : "+hex2byte(theKey));
         System.out.println("Message : "+hex2byte(theMsg));
         System.out.println("Cipher  : "+hex2byte(cryptMsg));
         System.out.println("Expected: "+hex2byte(theExp) + "\n");
     }
   }
   public static String hex2byte(byte[] array) {
        return DatatypeConverter.printHexBinary(array);
   }
   public static byte[] byte2hex(String s) {
        return DatatypeConverter.parseHexBinary(s);
   }
}

這是輸出:

Key     : 00000000000000000000000000000000
Message : F34481EC3CC627BACD5DC3FB08F273E6
Cipher  : 0336763E966D92595A567CC9CE537F5E0143DB63EE66B0CDFF9F69917680151E
Expected: 0336763E966D92595A567CC9CE537F5E

Key     : 00000000000000000000000000000000
Message : 9798C4640BAD75C7C3227DB910174E72
Cipher  : A9A1631BF4996954EBC093957B2345890143DB63EE66B0CDFF9F69917680151E
Expected: A9A1631BF4996954EBC093957B234589

Key     : 2B7E151628AED2A6ABF7158809CF4F3C
Message : 6BC1BEE22E409F96E93D7E117393172A
Cipher  : 3AD77BB40D7A3660A89ECAF32466EF97A254BE88E037DDD9D79FB6411C3F9DF8
Expected: 3AD77BB40D7A3660A89ECAF32466EF97

Key     : 2B7E151628AED2A6ABF7158809CF4F3C
Message : AE2D8A571E03AC9C9EB76FAC45AF8E51
Cipher  : F5D3D58503B9699DE785895A96FDBAAFA254BE88E037DDD9D79FB6411C3F9DF8
Expected: F5D3D58503B9699DE785895A96FDBAAF

為什么密碼長於預期。 這是來自參考書籍的可信的128位AES向量。

編輯添加到代碼:

cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] dcrypMsg = cipher.doFinal(cryptMsg);
System.out.println("Decrypted: " + byte2hex(dcrypMsg) + "\n");

解密是正確的,但我仍然無法理解......

Key     : 2B7E151628AED2A6ABF7158809CF4F3C
Message : AE2D8A571E03AC9C9EB76FAC45AF8E51
Cipher  : F5D3D58503B9699DE785895A96FDBAAFA254BE88E037DDD9D79FB6411C3F9DF8
Expected: F5D3D58503B9699DE785895A96FDBAAF
Decrypted: AE2D8A571E03AC9C9EB76FAC45AF8E51

請使用Cipher.getInstance("AES/ECB/NoPadding"); 為了確保,您的輸入不會被填充。 然后我得到了所有測試用例的預期輸出。

根據https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html

轉型的形式如下:

“algorithm / mode / padding”或“algorithm”(在后一種情況下,使用模式和填充方案的特定於提供者的默認值)。

你不知道,如果你沒有指定它,使用什么樣的填充。 我假設您的輸入數據被填充,這意味着您的輸入中會添加一些內容以填充它,這樣您就擁有了一組密碼塊大小的完整塊。 您的輸入長度已經被blocksize整除,因此會添加一個完整的塊,從而產生Message,其長度是預期的兩倍。

如果未指定密碼塊鏈接模式和填充算法,則JDK將采用默認值。 加密規范建議不要指定它們:

建議使用完全指定算法,模式和填充的轉換。 如果不這樣做,提供程序將使用默認值。 例如, SunJCE和SunPKCS11提供程序使用ECB作為默認模式,PKCS5Padding作為許多對稱密碼的默認填充。 http://docs.oracle.com/javase/7/docs/technotes/guides/security/crypto/CryptoSpec.html#trans

要獲得所需的輸出,您需要使用電子食譜模式(ECB) - 所以沒有塊鏈接 - 並且沒有填充:

Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");

暫無
暫無

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

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