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

TPM与TSS.NET密钥管理问题咨询:持久化与格式转换

TPM密钥管理与TSS.NET开发问题解答

1. 重启后按名称获取TPM中的指定密钥

TPM本身不支持“按名称直接检索密钥”的原生功能,临时TpmHandle在系统重启后会失效。解决方案是通过密钥持久化结合本地元数据存储实现:

实现步骤:

  • 创建密钥时,将其持久化到TPM的持久化Handle范围(0x81000000 - 0x81FFFFFF,这部分Handle重启后保留):
    // 假设keyHandle是临时密钥Handle,ownerAuth是TPM所有者授权
    var persistentHandle = new TpmHandle(0x81000001); // 自定义未被占用的持久化Handle
    tpm.EvictControl(AuthSession.FromOwnerAuth(ownerAuth), TpmHandle.RhOwner, keyHandle, persistentHandle);
    
  • 同时在本地安全存储(如Windows注册表、Credential Manager)中保存该密钥的名称哈希(keyPublic.Name.Hash)和对应的持久化Handle。
  • 重启后,遍历TPM中的持久化密钥,通过名称哈希匹配找到目标密钥,直接使用持久化Handle访问;或者直接通过保存的持久化Handle调用tpm.Load(如果密钥仍存在于TPM中)。

原理:

TPM的持久化Handle会在系统重启后保留,而每个TPM对象的Name是其唯一标识(由对象类型、属性和公共部分哈希生成),通过名称哈希可以精准匹配到目标密钥。

2. 将TPMPublic/TSSObject转换为服务器可用格式(XML/PEM)

TPMPublic包含标准RSA公钥的核心参数(模数、公钥指数),可以提取这些参数并转换为.NET原生支持的格式:

转换为XML:

// 假设tpmPublic是目标密钥的TPMPublic对象
var rsaPublic = tpmPublic.Parameters as RsaPublic;
var rsaParams = new RSAParameters
{
    Modulus = rsaPublic.Modulus,
    Exponent = rsaPublic.Exponent
};

using var rsa = RSA.Create();
rsa.ImportParameters(rsaParams);
string xmlString = rsa.ToXmlString(includePrivateParameters: false);

转换为PEM:

.NET原生没有直接导出PEM的API,可借助BouncyCastle库实现:

using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;

var rsaParams = new RsaKeyParameters(false, 
    new Org.BouncyCastle.Math.BigInteger(1, rsaPublic.Modulus), 
    new Org.BouncyCastle.Math.BigInteger(1, rsaPublic.Exponent));
using var writer = new StringWriter();
var pemWriter = new PemWriter(writer);
pemWriter.WriteObject(rsaParams);
string pemString = writer.ToString();

原理:

TPM的RSA公钥结构完全符合标准RSA公钥规范,提取模数和指数后,可直接映射到.NET的RSAParameters或BouncyCastle的密钥参数对象,进而转换为通用格式。

3. Import与Load中断后的密钥恢复

在Import和Load之间中断时,关键是保存Import操作返回的核心数据:

实现步骤:

  • 执行tpm.Import时,会返回ImportResponse对象,其中包含PrivateBlob(加密后的密钥材料,由父密钥保护)和Public(密钥的公共部分)。
  • 立即将PrivateBlob和Public序列化为字节流,存储到本地安全位置(如Windows Credential Manager),同时记录父密钥的持久化Handle或名称。
  • 恢复时,读取保存的PrivateBlob和Public,使用父密钥的Handle调用tpm.Load:
    // parentHandle是父密钥的持久化Handle,privateBlob是保存的字节流
    var loadResponse = tpm.Load(parentHandle, privateBlob);
    var restoredKeyHandle = loadResponse.ObjectHandle;
    

原理:

Import操作的本质是将外部密钥材料用父密钥的公钥加密,生成仅能由该父密钥解密的PrivateBlob。TPM不会自动保存这个Blob,必须由应用自行存储。只要拥有PrivateBlob和对应的父密钥,就能通过Load操作重新将密钥加载到TPM中,恢复临时Handle。

内容的提问来源于stack exchange,提问作者Michael R.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:02:30