You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Pkcs11Interop在Thales Luna HSM中解包的AES密钥无法持久化

问题描述

在.NET应用中使用Pkcs11Interop库与Thales Luna HSM通信,采用CKM_RSA_PKCS机制通过RSA密钥解包AES密钥。解包操作成功返回密钥句柄,且可在同一会话中用该密钥加密数据,但解包后的AES密钥并未持久化到HSM中。请问是否遗漏了相关参数?

代码片段

private void keyUnwrap() {

    string wrappedKey = "81C6CAD32431D506113CB07A515422ED55779CEE8B8A927C9898496F3209EC115EACAE2F59673A5F1423C6878A99FAD68E9741876A2605B2969953918BB9F6D15A4120A12F69EB2C752E8634B11ABB8FD709C072765361A0FAD7877CC3B8A78F500B4E3C8107BBDBE2DB0E82061EFB6E9FC885CAC5D0575324350D2FCAA08C89401F3B6ABEFA425A922A6A0F9FD2F61FCF37DDF9F7BF918B7C2C9228F033AC3EC2F35561FA0F7D397245CC37B2BEEDFB8028A0249DB8A7D13B22384C474629473FF153BAEEA06659F2A1B521066CB39835C7B3F18D7D33249834AC9667718564A2F8E46AA40A9EB7DFC365BA9C5A784599A2D99BD2F4E1462C849E2ED54D448B";

    List<ISlot> allSlots = pkcs11Library.GetSlotList(SlotsType.WithTokenPresent);

    using (ISession session = slot[0].OpenSession(SessionType.ReadWrite)) {

        // Login as normal user
        session.Login(CKU.CKU_USER, "CO_PIN");

        // get private key object
        IObjectHandle privateKey = findObject(session, CKO.CKO_PRIVATE_KEY, "Wrapping_RSA_Key_Pair_PRV");

        // Specify wrapping mechanism
        IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS);
        
        // Define attributes for unwrapped key
        List<IObjectAttribute> objectAttributes = new List<IObjectAttribute>();
        objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
        objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_KEY_TYPE, CKK.CKK_AES));
        objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ENCRYPT, true));
        objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DECRYPT, true));
        objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, "Unwrapped_AES_Key"));

        // Unwrap key
        IObjectHandle unwrappedKey = session.UnwrapKey(mechanism, privateKey, StringToByteArray(wrappedKey), objectAttributes);
        IObjectHandle newkey = findObject(session, CKO.CKO_SECRET_KEY, "Unwrapped_AES_Key");
        
        if (newkey == null) {
            throw new Exception("Unwrapped object not found.");
        }
    }
}


private IObjectHandle findObject(ISession session, CKO objectClass, string label) {
    // Prepare attribute template that defines search criteria
    List<IObjectAttribute> objectAttributes = new List<IObjectAttribute>();
    objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, objectClass));
    objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, label));
    // Initialize searching
    session.FindObjectsInit(objectAttributes);
    // Get search results
    List<IObjectHandle> foundObjects = session.FindObjects(1);
    // Terminate searching
    session.FindObjectsFinal();

    if (foundObjects.Count > 0) {
        return foundObjects[0];
    }

    return null;
}

public static byte[] StringToByteArray(string hex)
{
    return Enumerable.Range(0, hex.Length)
                     .Where(x => x % 2 == 0)
                     .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                     .ToArray();
}

问题解答

核心原因

默认情况下,UnwrapKey创建的是会话临时密钥——仅在当前会话内有效,会话关闭后自动销毁,不会持久化到HSM令牌中。你遗漏了CKA_TOKEN属性,该属性用于指定密钥是否存储为HSM上的持久化令牌对象。

修复方案

在定义解包密钥的属性列表时,添加CKA_TOKEN属性并设置为true,同时建议补充CKA_PRIVATE属性增强安全性:

List<IObjectAttribute> objectAttributes = new List<IObjectAttribute>();
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_KEY_TYPE, CKK.CKK_AES));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ENCRYPT, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DECRYPT, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, "Unwrapped_AES_Key"));
// 关键:标记密钥为持久化令牌对象
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
// 可选:设置密钥为私有,仅当前用户可见
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, true));

补充说明

  • CKA_TOKEN=true:将密钥从会话临时对象转为HSM令牌持久化对象,会话关闭后仍保留在HSM中;默认false为会话临时对象。
  • CKA_PRIVATE=true:限制密钥仅对创建它的用户可见,避免其他用户未经授权访问,提升安全性。
  • 权限检查:确保当前登录的HSM用户拥有创建持久化密钥的权限,权限不足会导致操作失败。

内容的提问来源于stack exchange,提问作者IuR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:24:53