HSM解密+加密链

HSM decryption + encryption chaining

我的应用程序充当交换台,在两方之间传输非常敏感的消息,我想弄清楚如何在没有 "looking" 他们试图发送的消息的情况下做到这一点。

我有一个 HSM,我已经为发件人生成了一个密钥对 - 他们将使用我给他们的 public 密钥加密消息,我可以使用我在 HSM 中的私钥。

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

有没有什么方法可以将这两个操作链接到 HSM 中,而不让解密消息靠近我的应用程序内存?我希望明文内容永远不会离开 HSM 的边界。

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

如果您只需要用不同的密钥重新加密相同的秘密,您可以使用 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);

祝你好运!