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.
相关产品推荐
相关产品推荐

