【问题标题】:HSM decryption + encryption chainingHSM解密+加密链接
【发布时间】:2019-07-30 06:10:46
【问题描述】:

我的应用程序充当交换机,在两方之间传输非常敏感的消息,我试图弄清楚如何在不“查看”他们尝试发送的消息的情况下做到这一点。

我有一个 HSM,并且我已经为发件人生成了一个密钥对 - 他们将使用我提供给他们的公钥加密消息,我可以使用我在高速电机。

然后,我将通过使用我拥有的最终接收者的公钥对其进行加密来传递该消息。

有没有办法在 HSM 中链接这两个操作,而在我的应用程序内存附近没有解密的消息?我希望明文内容永远不会离开 HSM 的边界。

我知道一些 HSM 具有 CodeSafe / SEE 机器功能,可以让我编写嵌入式系统代码并在 HSM 中运行它,在我开始之前,我想看看是否有使用通用 PKCS / JCE 的方法/CNG API 安全地执行此操作。

【问题讨论】:

  • 我认为您可以通过密钥包装来做到这一点。使用发送者的私钥来解包每条消息的对称密钥:你得到一个对称密钥的句柄,而不是对称密钥本身,然后你用下一个接收者的公钥来包装它。
  • 部分 HSM 提供翻译数据功能,您可以将传入数据 key1 中的数据翻译(使用 key1 解密并使用 key2 加密)到传出密钥 key2,该操作发生在 HSM 内部,因此您不会真的被触摸清除数据,但这些命令看起来仅使用对称密钥,在这种情况下,您必须为对称数据密钥设置密钥交换机制
  • ...我已经为发送者生成了一个密钥对... 那么,游戏结束了,你可以阅读他们所有的消息了。
  • AFAIK 没有一个常见的加密 API 支持安全重新加密。顺便说一句,几个月前我回答了similar question for PKCS#11 interface
  • @JamesKPolk 是的,但是发件人向我支付了一大笔钱,以便将消息安全地散播到我正在管理其公钥的数万台设备。他们相信我做对了,这就是为什么他们用我给他们的公钥加密它。我正在努力确保有效载荷到达所有目的地,而我、我的团队、员工或黑客永远无法看到它。

标签: encryption pkcs#11 jce hsm cng


【解决方案1】:

如果您只需要在不同的密钥下重新加密相同的秘密,您可以使用 C_Unwrap 创建一个具有已翻译秘密值的临时 HSM 对象,然后使用 C_Wrap 加密此值所有收件人的时间 HSM 对象。

这样秘密就永远不会离开 HSM。

类似这样的东西(已验证可在带有 RSA-OAEP 的 SafeNet Luna 7 上工作):

// Your private key for 'decrypting' secret. Must have key unwrapping allowed
CK_OBJECT_HANDLE hsmPrivateKey = ... ;

// Encrypted secret
byte[] wrappedKey = ... ; // 

// Template for temporal generic secret key with value of the secret
CK_ATTRIBUTE[] tempTemplate = new CK_ATTRIBUTE[] {
        new CK_ATTRIBUTE(CKA.CLASS, CKO.SECRET_KEY),
        new CK_ATTRIBUTE(CKA.KEY_TYPE, CKK.GENERIC_SECRET),
        new CK_ATTRIBUTE(CKA.TOKEN, false),
        new CK_ATTRIBUTE(CKA.PRIVATE, true),
        new CK_ATTRIBUTE(CKA.EXTRACTABLE, true),
        new CK_ATTRIBUTE(CKA.SENSITIVE, true),
        new CK_ATTRIBUTE(CKA.ENCRYPT, false),
        new CK_ATTRIBUTE(CKA.DECRYPT, false),
        new CK_ATTRIBUTE(CKA.WRAP, false),
        new CK_ATTRIBUTE(CKA.UNWRAP, false),
        new CK_ATTRIBUTE(CKA.SIGN, false),
        new CK_ATTRIBUTE(CKA.VERIFY, false),
        new CK_ATTRIBUTE(CKA.DERIVE, false)
};

// Unwrapping/decryption mechanism
CK_MECHANISM mechanism = ... ;

// Handle for temporal generic secret key with value of the secret
CK_OBJECT_HANDLE temporalValueHandle = new CK_OBJECT_HANDLE();

// Unwrap/decrypt the secret into temporal key
CryptokiEx.C_UnwrapKey(session, mechanism, hsmPrivateKey, wrappedKey, wrappedKey.length, tempTemplate, tempTemplate.length, temporalValueHandle);

// Wrap/encrypt the secret for recipients. Recipient public keys must have key wrapping allowed
for(CK_OBJECT_HANDLE recipientPublicKey : ... ) {
    LongRef resSize = new LongRef(0);
    CryptokiEx.C_WrapKey(session, mechanism, recipientPublicKey, temporalValueHandle, null, resSize);
    byte[] rewrappedKey = new byte[CryptokiUtils.safeIntCast(resSize.value)];
    CryptokiEx.C_WrapKey(session, mechanism, recipientPublicKey, temporalValueHandle, rewrappedKey, resSize);
    System.out.println("Re-wrapped key: " + bytesToHexString(rewrappedKey));
}

// Delete temporal generic secret key
CryptokiEx.C_DestroyObject(session, temporalValueHandle);

祝你好运!

【讨论】:

  • 恐怕这个解决方案不能满足 OP 的要求“在我的应用程序内存附近没有解密的消息”。
  • @jariq 为什么——解密的消息在 HSM 中作为通用密钥。应用程序只有这个键的句柄。给定这个通用密钥的模板,它是敏感的......应用程序对密钥所做的所有事情就是它用“接收者”(无论他们是谁)的公钥包装它......
  • 很抱歉,我没有注意到您使用的是通用密钥。这是一个非常有趣的想法,值得探索!现在我想知道通用键值的大小限制是多少。
  • @jariq 我从未尝试过,但 Luna 7 声称支持生成(通过 CKM_GENERIC_SECRET_KEY_GEN)长达 512 字节的通用密钥。另请注意,wrap/unwrap 密钥没有多部分变体。
猜你喜欢
  • 2017-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2011-07-31
  • 2023-04-08
相关资源
最近更新 更多