首页 > 解决方案 > 在使用带有“AES/CBC/PKCS5Padding”的 Java Cipher 进行解密时,是否必须指定 IV?并且只能使用 SecretKeyFactory 吗?

问题描述

我阅读了一些关于使用 Java Cipher 加密和解密数据的示例。例如:

KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom();
keyGenerator.init(256, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, secretKey);

我有两个关于解密过程的问题。

  1. 虽然 IV 是必需的,但我们可以使用Cipher.init(Cipher.ENCRYPT_MODE, Key). 随机 IV 将自动应用到它。但是,在解密模式下,必须使用相同的 IV。这是否意味着Cipher.init(int opmode, Key key, AlgorithmParameters params)应该只使用 并且应该从加密中获取IV,存储并在此处传递?

除了'''KeyGenerator''',我还看到了使用'''SecretKeyFactory'''生成密钥的示例:

String key = ...
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKeySpec keySpec = factory.generateSecret(new DESKeySpec(key));

如果我将最后一行更改为,我想我可以将它用于 AES

SecretKeySpec keySpec = factory.generateSecret(new SecretKeySpec(key,"AES"));
  1. 我对何时使用SecretKeyFactory生成密钥以及何时使用KeyGenerator. 似乎后者是生成随机密钥,前者是从给定的密钥材料生成的。那么是不是意味着在解密模式下,只能使用 SecretKeyFactory 呢?

标签: javaencryptionjcejca

解决方案


这是否意味着Cipher.init(int opmode, Key key, AlgorithmParameters params)应该只使用 并且应该从加密中获取IV,存储并在此处传递?

是的,正是如此,除非您能够以其他方式进行交流。通常,尽管 IV 在加密期间是随机的,然后作为密文的前缀。对于 AES-CBC,它的大小始终与块大小相同:16 字节。

那么是不是意味着在解密模式下,只能SecretKeyFactory使用呢?

是的,尽管 AES 有一个简洁的捷径;你可以简单地做:

SecretKey aesKey = new SecretKeySpec(keyBytes, "AES");

并完成它。这是因为SecretKeySpec实现SecretKey. 对于 3DES 密钥,这不是一个好主意,因为这意味着 DES 的奇偶校验位设置不正确。然而,诸如 AES 密钥和 HMAC 密钥之类的现代密钥仅由随机数据组成,因此对它们来说没问题。有一个警告:如果您尝试以这种方式在硬件设备中生成密钥,那将是一个问题:它必须保存在软件中。

请注意,我不会深入研究密钥管理以及如何创建密钥。我已经在这里回答了这个问题,尽管这个答案肯定还远未完成。哎呀,你可以使用骰子并通过电话分享我关心的数字:)


推荐阅读