java - 将 PBKDF2 盐重新用于 AES/GCM 作为 IV : dangerous?

标签 java encryption cryptography pbkdf2 aes-gcm

我正在开发一个加密实用程序类,以便在常见操作中重复使用。

一个非常常见的情况是使用用户提供的密码来加密明文。
在这种情况下,我使用 PBKDF2 派生一个有效的 AES key ,然后在 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。

盐和 IV 都可以公开,但不应重复使用。

是否应该理解它们不应在相同的功能/服务/算法中重复使用,或者它们不应在任何地方重复使用?

修改此方法以生成不同的盐和 IV 非常容易,但是否有理由这样做?

谢谢

最佳答案

请注意,您可能不需要重新生成随机 IV,只要您更改 salt 并因此更改生成的 key 。如果您不在每次(重新)加密时更改盐值,那么您确实需要一个单独的 IV,否则您可能会将信息泄露给对手。

您可以保持盐和 IV 相同。但通常更容易从密码和盐中导出 IV 和 key 。如果您将 PBKDF2 与 SHA-512 散列一起使用,这很简单:只需从生成的散列中获取 128、192 或 256 位 AES key ,然后将另外 128 个后续位作为 IV 并使用它。

如果您需要多个 key 或者如果您使用较小的散列,那么您可能需要从 PBKDF2 的结果中派生出更多的 key 。在那种情况下,最好将 PBKDF2 的结果标记为主 key 并从中执行 N 个 key 派生,一个用于每个 key ,一个用于 IV。你可以使用例如HKDF 为此,Bouncy CaSTLe 有一个实现(我为此提供了初始源代码)。

关于java - 将 PBKDF2 盐重新用于 AES/GCM 作为 IV : dangerous?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48709703/

相关文章:

java - 项目监听器不起作用

java - 将 JQuery 添加到 java servlet

go - 将 os.Stdin 转换为 []byte

java - PBEWithHmacSHA512AndAES_128 和 AES 模式(如 GCM)

java - 无法让 Servlet 以 UTF-8 格式处理请求内容

java - 如何使用spring动态加载java中的配置

php - 在PHP openssl_encrypt和golang河豚中匹配河豚加密

javascript - 在 Service-Worker 中使用 Crypto Node.js 加密并使用 window.crypto 解密

python - 基于字符串的协议(protocol)安全基础

javax.crypto.BadPaddingException : Decryption error when using Java RSA encryption