2

我有一段代码,我用 AES 密钥包装我的对称密钥(AES):

  1. swkKey:这是用于包装的 AES 密钥。
  2. key:要包装的密钥。

代码:

SecretKey swkKeySpec = new SecretKeySpec(swkKey, 0, swkKey.length, "AES");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
final int ivLength = 12;
final IvParameterSpec iv = createIV(ivLength);///Creates a new array.
cipher.init(Cipher.WRAP_MODE, swkKeySpec, iv);
SecretKey sKeySpec = new SecretKeySpec(key, 0, key.length, "AES");
byte[] wrappedAppKey = cipher.wrap(sKeySpec);`

如果 key 是 256 位而 swkkey 是 256 位,则 WrappedAppKey 的长度是多少。包装的密钥可以超过 32 个字节吗?请注意,在这种情况下,我会收到以下日志:

key length: 32(key to be wrapped)
swkKey length: 32(key used to wrap)
wrappedAppKey size: 48(final wrapped key output).
4

1 回答 1

7

使用标准操作模式的包装密钥只是对密钥的编码数据进行加密。由于 AES 密钥的编码数据与原始数据相同,因此 256 位密钥的数据仅为 32 个字节。

这些非专用模式(如 GCM/CBC/ECB)的主要区别在于如何处理关键字节:它们直接在SecretKey实例中使用,而不是作为字节返回。这一点非常重要,特别是如果操作是在硬件(智能卡、HSM、TPM)而不是软件中执行的;然后可以在专用设备中保存/保护包装密钥的字节。

GCM 在下面使用 CTR 模式,这是一种流操作模式。流操作模式不需要填充明文,因此密文也将只是 32 个字节。Java 还将身份验证标签 (t) 包含在计算中。默认情况下,GCM 使用最大身份验证标签大小,即 16 个字节,因此将其添加到密钥本身的密文中,剩下 48 个字节。可以使用更专业的GCMParameterSpec类而不是ivParameterSpec;来配置标签大小。请注意,较小的标签大小可能会引入 GCM 模式的漏洞。

但是,请记住,还需要能够为 GCM 模式加密重新生成 IV/nonce。所以如果它不能从上下文中重新生成,你也需要存储它。还要注意,如果随机数被重复用于相同的包装密钥,GCM 模式会以一种可怕的方式中断。大多数时候使用完全随机的随机数,因此将其与密文一起存储是非常重要的。对于 GCM,强烈建议使用 12 字节的 nonce,将密文扩展到 60 字节。

或者,可以使用 SIV 模式或 GCM-SIV 模式。这些模式使用身份验证标签作为“合成”IV。这使得加密具有确定性(相同的明文导致相同的密文)。由于密钥本身应该是随机的,因此它们对于这类模式非常有用,因为它们不需要使用 RNG 或存储 IV。不幸的是,通用加密库通常不包含这些模式的实现。

于 2019-03-11T15:35:29.917 回答