2

我看到了一个通过以下步骤生成 AES 密钥的代码片段:

  1. 生成一个 16 字节的随机值数组。

    SecureRandom random = new SecureRandom();
    byte[] key = new byte[16];
    random.nextBytes(key); 
    
  2. 将 HKDF 应用于密钥以生成新的加密密钥。

encrypt_key = KeyDerivation.hkdfSha256(Key,
                           /* inputSalt =*/ null,
                           hkdfInfoString.getBytes("UTF-8"),
                           16);

我很困惑为什么我们需要两个步骤。SecureRandom 似乎为密钥提供了足够的熵,对吧?两个问题:

  1. 我们可以key直接使用 1) 进行 AES 加密吗?
  2. 2)中的空盐有什么影响?我正在考虑可能额外的步骤 2)是为了保护被泄露的密钥(只是一个猜测)。如果是,空盐是否使目的无效?因为我们可以预先计算 HKDF 的输入密钥材料与其输出之间的联系。

HKDF 声称盐是可选的,尽管使用随机盐确实可以增强它。我很困惑什么时候需要 HKDF(尤其是没有盐)。如果我们已经有一个具有足够熵的密钥,为什么我们需要它?如果我们有一个没有足够熵的弱密钥,HKDF(没有盐)如何帮助这种情况?我想象攻击者可以预先计算出弱密钥与生成密钥之间的映射,对吧?

4

1 回答 1

2
  1. 我们可以直接使用 1) 中的密钥进行 AES 加密吗?

是的你可以。但是,您需要经常更改密钥是有原因的,例如算法/方案限制、不泄漏(主)密钥、扩展密钥材料、派生多个密钥和/或 IV 值等......以及首先需要 KBKDF 的任何东西(HKDF 是基于散列的基于密钥的密钥派生函数)。

但是,如果只有一个 128 位密钥是从另一个 128 位密钥派生的,那么我看不到太多好处。这可能有用的唯一情况是,如果您不信任SecureRandom实现的安全性,因为 KDF 放置了另一层 HMAC 以在攻击者尝试猜测(显然很弱)随机数生成器的状态时突破.

当然,正如您在问题中所指出的那样,攻击者仍然可以猜测随机发生器的状态,但至少攻击者无法通过例如反转计算或获取有关状态的统计信息来获取有关状态的信息。

  1. 2)中的空盐有什么影响?我正在考虑可能额外的步骤 2)是为了保护被泄露的密钥(只是一个猜测)。如果是,空盐是否使目的无效?因为我们可以预先计算 HKDF 的输入密钥材料与其输出之间的联系。

不,无论盐是否存在,密钥派生函数都是单向的。该盐用于 HKDF 的安全证明中。然而,实际上并不需要提供足够的安全性。如果您可以添加/存储/传输盐,那么它将有利于安全性,但是有很多 KBKDF 首先(明确)不允许使用盐。另一方面:像 PBKDF2 这样的基于密码的 KDF 确实需要一个盐来保证安全。

于 2020-10-17T14:02:19.013 回答