【问题标题】:How to sign message with TPM2?如何使用 TPM2 签署消息?
【发布时间】:2025-11-27 23:10:02
【问题描述】:

来自MethodA()

首先我创建了模板,然后是签名密钥。然后使用ContextSave(); 保存上下文并将其编组到文件中。

来自MethodB()

我解组了文件,并做了ContextLoad(); 这里它通过完整性检查失败。我做错了什么?

我创建了这样的签名密钥:

var keyTemplate = new TpmPublic(TpmAlgId.Sha1,          // Name algorithm
     ObjectAttr.UserWithAuth | ObjectAttr.Sign |        // Signing key
     ObjectAttr.FixedParent | ObjectAttr.FixedTPM |     // Non-migratable 
     ObjectAttr.SensitiveDataOrigin,
     null,                                              // No policy
     new RsaParms(new SymDefObject(),
                  new SchemeRsassa(TpmAlgId.Sha1), 2048, 0),
     new Tpm2bPublicKeyRsa());


TpmHandle keyHandle = tpm[ownerAuth].CreatePrimary(
     TpmRh.Owner,                            // In the owner-hierarchy
     new SensitiveCreate(keyAuth, null),     // With this auth-value
     keyTemplate,                            // Describes key
     null,                                   // Extra data for creation ticket
     new PcrSelection[0],                    // Non-PCR-bound
     out keyPublic,                          // PubKey and attributes
     out creationData, out creationHash, out creationTicket);    // Not used here

编辑1:

方法A();

        public static void MethodA()
    {
        try
        {
            Tpm2Device tpmDevice = new TcpTpmDevice(tpm_host, tpm_port);
            //Tpm2Device tpmDevice = new TbsDevice();
            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);
            if (tpmDevice is TcpTpmDevice)
            {
                tpmDevice.PowerCycle();
                tpm.Startup(Su.Clear);
            }


            // 
            // The TPM needs a template that describes the parameters of the key
            // or other object to be created.  The template below instructs the TPM 
            // to create a new 2048-bit non-migratable signing key.
            // 
            var keyTemplate = new TpmPublic(TpmAlgId.Sha1,                                  // Name algorithm
                                        ObjectAttr.UserWithAuth | ObjectAttr.Sign |     // Signing key
                                        ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-migratable 
                                        ObjectAttr.SensitiveDataOrigin,
                                        null,                                    // No policy
                                        new RsaParms(new SymDefObject(),
                                                     new SchemeRsassa(TpmAlgId.Sha1), 2048, 0),
                                        new Tpm2bPublicKeyRsa());



            //
            // AuthValue encapsulates an authorization value: essentially a byte-array.
            // OwnerAuth is the owner authorization value of the TPM-under-test.  We
            // assume that it (and other) auths are set to the default (null) value.
            // If running on a real TPM, which has been provisioned by Windows, this
            // value will be different. An administrator can retrieve the owner
            // authorization value from the registry.
            //
            //var ownerAuth = new AuthValue();

            // 
            // Authorization for the key we are about to create.
            // 
            var keyAuth = new byte[] { 1, 2, 3 };

            TpmPublic keyPublic;
            CreationData creationData;
            TkCreation creationTicket;
            byte[] creationHash;

            // 
            // Ask the TPM to create a new primary RSA signing key.
            // 
            TpmHandle keyHandle = tpm[ownerAuth].CreatePrimary(
                TpmRh.Owner,                            // In the owner-hierarchy
                new SensitiveCreate(keyAuth, null),     // With this auth-value
                keyTemplate,                            // Describes key
                null,                                   // Extra data for creation ticket
                new PcrSelection[0],                    // Non-PCR-bound
                out keyPublic,                          // PubKey and attributes
                out creationData, out creationHash, out creationTicket);    // Not used here



            // 
            // Print out text-versions of the public key just created
            // 
            //Console.WriteLine("New public key\n" + keyPublic.ToString());



            Context ctx = tpm.ContextSave(keyHandle);
            File.WriteAllBytes("key.bin", Marshaller.GetTpmRepresentation(ctx));






            // Clean up.
            tpm.FlushContext(keyHandle);
            tpm.Dispose();


        }
        catch (Exception e)
        {
            Console.WriteLine("Exception occurred: {0}", e.Message);
        }


    }

方法B():

public static void MethodB()
    {
       try
        {
            Tpm2Device tpmDevice = new TcpTpmDevice(tpm_host, tpm_port);
            //Tpm2Device tpmDevice = new TbsDevice();
            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);
            if (tpmDevice is TcpTpmDevice)
            {
                tpmDevice.PowerCycle();
                tpm.Startup(Su.Clear);
            }




            Context ctx2 = Marshaller.FromTpmRepresentation<Context>(File.ReadAllBytes("key.bin"));
            TpmHandle keyHandle = tpm.ContextLoad(ctx2); //integrity check fail

【问题讨论】:

  • 很难用这个小代码sn-p看到。需要所有代码。
  • 添加了完整的 MethodA() 和 MethodB() 以指出失败的位置。
  • MethodB() 中似乎清除了 TPM,这是错误的。当然,完整性检查会失败,因为密钥已经丢失。
  • 谢谢,几天前我意识到,你可以c/p你的评论来回答,所以我可以接受。

标签: tpm


【解决方案1】:

此代码在MethodA()MethodB() 中都有:

if (tpmDevice is TcpTpmDevice)
{
    tpmDevice.PowerCycle();
    tpm.Startup(Su.Clear);
}

这是 TSS MSR 示例中的常见模式。它会检查您正在与之交谈的 TPM 是否是模拟设备,如果是,则在其上执行 Clear 命令,确保您从一个干净的状态开始。在MethodA() 中执行此操作很好,但通过在MethodB() 中执行此操作,您基本上撤消了您在MethodA() 中执行的操作:您刚刚创建的密钥被删除,因此完整性检查失败。

【讨论】: