【发布时间】:2018-07-20 10:51:33
【问题描述】:
我正在开发一个加密实用程序类,可重复用于常见操作。
一种非常常见的情况是使用用户提供的密码加密明文。
在这种情况下,我使用 PBKDF2 导出有效的 AES 密钥,然后在 GCM 模式下使用它来加密明文。
一些代码:
// IV_LEN = 96
// ITERATIONS = 1000 ~ 4000
// KEY_LEN = 128 ~ 256
// TAG_LEN = 128
public static String encrypt(byte[] plain, char[] password) throws GeneralSecurityException
{
SecureRandom rng = SecureRandom.getInstanceStrong();
byte[] iv = new byte[IV_LEN / 8];
rng.nextBytes(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
SecretKey derivedKey = factory.generateSecret(new PBEKeySpec(password, iv, ITERATIONS, KEY_LEN));
SecretKey secretKey = new SecretKeySpec(derivedKey.getEncoded(), "AES");
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
c.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(TAG_LEN, iv));
byte[] encrypted = c.doFinal(plain);
Encoder encoder = Base64.getUrlEncoder().withoutPadding();
return encoder.encodeToString(iv) + ":" + encoder.encodeToString(encrypted);
}
目前,我也在使用 PBKDF2 salt(96 位 - SecureRandom)作为 AES/GCM 加密的 IV。
salt 和 IV 都可以公开,但不应重复使用。
是否应该理解它们不应该在同一个功能/服务/算法中重复使用,或者它们不应该在任何地方重复使用?
修改这个方法很容易生成不同的盐和IV,但是有这样做的理由吗?
谢谢
【问题讨论】:
-
有什么理由不这样做吗?
-
@erickson 实际上,不 - 这只是病态的好奇心......并且返回的记录要短一些字节! :)
-
@James“我认为你应该写”好吧,我没有这样做的经验或证书,你会是一个更好的候选人。 ??????
-
@JamesKPolk 也许类似下面的内容可能会从 RFC 5084 等中提取一些概念:{ algorithm:{ name: mode: key_size: block_size: } mode: { name initializer } padding: { name: } key_derivation: { name: key: count: } authentication: { hash_name: key_method: } Additional: { user defined key/value fields } } data 但这对于仅加密一两个块是不实用的。现在轮到你了。
标签: java encryption cryptography pbkdf2 aes-gcm