这个AES 128加密有什么问题?

3

我不明白为什么我的密文长度比以下向量预期输出的长度要长。我不会解释代码,因为我认为它非常整洁和清晰。

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
2个回答

4
请使用 Cipher.getInstance("AES/ECB/NoPadding");,以确保您的输入不会被填充。这样可以为所有测试用例获得预期输出。 根据https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html
一个转换的格式如下: "algorithm/mode/padding" 或者 "algorithm" (在后一种情况下, 使用提供程序特定的默认值作为模式和填充方案)。
如果不指定填充方式,则无法知道所使用的填充方式。我假设您的输入数据会进行填充,这意味着会添加一些内容来填满输入数据,使其成为密钥块大小的完整块组。由于您的输入长度已经可被密钥块大小整除,因此会添加一个完整块,从而导致消息长度是预期长度的两倍。

2
如果您未指定密码块链接模式和填充算法,则JDK将采用默认值。加密规范建议不要这样做:
建议使用完全指定算法、模式和填充的转换方式。否则,提供者将使用默认值。例如,SunJCE和SunPKCS11提供者在许多对称密码中使用ECB作为默认模式,并使用PKCS5Padding作为默认填充。
要获得所需的输出,您需要使用电子烹饪书模式(ECB)-因此没有块链接-也没有填充。
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接