重复使用PBKDF2盐用于AES / GCM IV:危险吗?

时间:2018-02-09 16:02:50

标签: java encryption cryptography pbkdf2 aes-gcm

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

一个非常常见的情况是使用用户提供的密码加密明文 在这种情况下,我使用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盐(96位 - SecureRandom)作为AES / GCM加密的IV。

盐和Ⅳ都可以是公开的,但它们不应该被重复使用。

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

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

由于

1 个答案:

答案 0 :(得分:3)

请注意,只要更改salt以及生成的密钥,就不需要重新生成随机IV。如果您每次(重新)加密时都不更改盐,那么您需要单独的IV,否则您可能会向对手泄露信息。

你可以保持盐和IV相同。但通常更容易从密码和盐中获取密钥和密钥。如果你使用带有SHA-512哈希值的PBKDF2,这很简单:只需从生成的哈希中获取128,192或256位AES密钥,然后将另外128个后续位作为IV并使用它。

如果您需要多个密钥或者使用较小的哈希,则可能需要从PBKDF2的结果中获取更多密钥。在这种情况下,最好将PBKDF2的结果标记为主密钥,并从中执行N个密钥推导,每个密钥一个,IV一个。你可以用例如HKDF为此,Bouncy Castle有一个实现(我提供了初始源代码)。