0

我想知道是否可以使用 AES_CMAC 机制进行密钥派生。

我有一个 AES 主密钥(密钥),我想生成一个 AES 密钥:key2 = AES_CMAC(key, data)。当然,我只想获得 key2 持有者,而不是价值。

当我这样做时:

public long derive_key(long key, byte[] data, String label) {
         long p_key = -1L;
         CK_MECHANISM mec = new CK_MECHANISM();
         mec.mechanism = PKCS11Constants.CKM_AES_CMAC;
         SecretKey keyTemplate = new AESSecretKey();
         
         fill(keyTemplate, label);
         ((AESSecretKey) keyTemplate).getValueLen().setLongValue(16L);
         ((AESSecretKey) keyTemplate).getValue().setByteArrayValue(data);
         
         CK_ATTRIBUTE[] attr = iaik.pkcs.pkcs11.objects.Object.getSetAttributes(keyTemplate);
         return cryptoki.C_DeriveKey(ckiSession, mec, key, attr, true);

我收到 CKR_MECHANISM_INVALID 错误。

而且我不能使用 cryptoki.C_Sign(...) 因为它输出密钥值。

谢谢!

4

2 回答 2

0

CKM_AES_CMAC机制不能用于密钥派生(参见此处的表格)。

在我看来,在不暴露任何中间结果的情况下,不可能通过标准 PKCS#11 机制实现 CMAC 密钥派生(有关将多个中间结果泄漏到 SW 的方法,请参见下文)。

鉴于CMAC 的工作方式,您无法执行子密钥推导(条件 XOR 和按位移位)和最后一个输入块调整。

在我看来,您有以下选择:

  • 使用另一种密钥派生算法

  • 将此机制实现为 HSM 中的自定义代码(参见例如此处

  • 使用另一种技术(例如自定义智能卡)

祝你的项目好运!


从理论上讲,如果您不介意在 SW 中公开 E(k,0)、子键和一个中间结果,您可以:

  • 通过计算 E(k,0)CKM_AES_ECB

  • 计算 SW 中的子键

  • 通过计算输入数据块 m_{1}..m_{n-1} 的 CBC-MACCKM_AES_MAC

  • 在 SW 中使用适当的子键(如果块不完整,则使用 ISO 9797-1 填充方法 2)调整最后一个输入数据块 m_{n}

  • 使用CKM_AES_CBC_ENCRYPT_DATA等于计算出的 CBC-MAC 的 IV 和等于调整后的最后一个块的数据来导出密钥

不要那样做!(尽管它可能比在 SW 中做这一切要好)。

免责声明:我不是加密专家,所以请验证我的想法。

于 2021-02-10T01:00:18.823 回答
0

PKCS#11 确实定义了 CKM_SP800-108_COUNTER_KDF(以及 _FEEDBACK_KDF 和 DOUBLE_PIPELINE_KDF),它允许您使用 AES_CMAC 作为所使用的底层算法。这能满足你的需求吗?可能还有其他密钥派生机制也可以让您使用 CMAC。

但一个更普遍的问题是你想要实现什么。通常,推导是根据具有附加要求的更大方案的要求进行的。如果您特别要求 CMAC,我怀疑您还有其他要求要满足吗?

于 2021-05-28T16:45:10.480 回答