How to export public key from TPM with TSS.net?

℡╲_俬逩灬. 提交于 2020-08-10 23:41:43

问题


I've gotten the Signing sample from here to run against the TPM Simulator.

It looks like I have some sort of reference to the public key after calling:

TpmPublic keyPublic; //This seems to have what we're looking for
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); 

There is some commented code further on that hint at a previous way to export the public key:

// (Note that serialization is not supported on WinRT)
// 
// Demonstrate the use of XML persistence by saving keyPublic to 
// a file and making a copy by reading it back into a new object
// 
// NOTE: 12-JAN-2016: May be removing support for policy
//       serialization. We'd like to get feedback on whether
//       this is a desirable feature and should be retained.
//
// {
//     const string fileName = "sample.xml";
//     string xmlVersionOfObject = keyPublic.GetXml();
//     keyPublic.XmlSerializeToFile(fileName);
//     var copyOfPublic = TpmStructureBase.XmlDeserializeFromFile<TpmPublic>(fileName);

The TpmPublic.GetXml() doesn't appear to exist any more, so it may have been removed per the note.


回答1:


It's not entirely clear what you need; what is the type of your public key and what do you want to do with it? So this answer is assuming that you're trying to get to the raw bytes of the exponent and the modulus of an RSA public key so you can export them out to a key that can then be used by, for example, OpenSSL.

The "XML export" functionality you saw refers to serializing and de-serializing a TpmPublic object and doesn't really get you any closer to your goal: you would simply get the original object back. It was probably removed because it wasn't working very well.

Assuming that keyPublic is your TpmPublic object representing an RSA key, to get the exponent you would do:

var rsaParams = (RsaParms)keyPublic.parameters;
var exponent = rsaParams.exponent != 0
             ? Globs.HostToNet(rsaParams.exponent)
             : RsaParms.DefaultExponent;

And to get the modulus:

var modulus = (keyPublic.unique as Tpm2bPublicKeyRsa).buffer;

To see how ECC keys are handled, take a look at AsymCryptoSystem.CreateFrom():

public static AsymCryptoSystem CreateFrom(TpmPublic pubKey, TpmPrivate privKey = null)
{
    var cs = new AsymCryptoSystem();

    TpmAlgId keyAlgId = pubKey.type;
    cs.PublicParms = pubKey.Copy();

    // Create an algorithm provider from the provided PubKey
    switch (keyAlgId)
    {
        case TpmAlgId.Rsa:
            {
                RawRsa rr = null;
                byte[] prime1 = null,
                        prime2 = null;
                if (privKey != null)
                {
                    rr = new RawRsa(pubKey, privKey);
                    prime1 = RawRsa.ToBigEndian(rr.P);
                    prime2 = RawRsa.ToBigEndian(rr.Q);
                }
                var rsaParams = (RsaParms)pubKey.parameters;
                var exponent = rsaParams.exponent != 0
                                        ? Globs.HostToNet(rsaParams.exponent)
                                        : RsaParms.DefaultExponent;
                var modulus = (pubKey.unique as Tpm2bPublicKeyRsa).buffer;
                AsymmetricKeyAlgorithmProvider rsaProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaOaepSha256);

                uint primeLen1 = 0, primeLen2 = 0;
                // Compute the size of BCRYPT_RSAKEY_BLOB
                int rsaKeySize = exponent.Length + modulus.Length + 24;
                if (prime1 != null && prime1.Length > 0)
                {
                    if (prime2 == null || prime2.Length == 0)
                    {
                        Globs.Throw<ArgumentException>("LoadRSAKey(): The second prime is missing");
                        return null;
                    }
                    primeLen1 = (uint)prime1.Length;
                    primeLen2 = (uint)prime2.Length;
                    rsaKeySize += prime1.Length + prime2.Length;
                }
                else if (prime2 != null && prime2.Length > 0)
                {
                    Globs.Throw<ArgumentException>("LoadRSAKey(): The first prime is missing");
                    return null;
                }

                var rsaKey = new byte[rsaKeySize];

                // Initialize BCRYPT_RSAKEY_BLOB
                int offset = 0;
                WriteToBuffer(ref rsaKey, ref offset, primeLen1 == 0 ?
                                BCRYPT_RSAPUBLIC_MAGIC : BCRYPT_RSAPRIVATE_MAGIC);
                WriteToBuffer(ref rsaKey, ref offset, (uint)modulus.Length * 8);
                WriteToBuffer(ref rsaKey, ref offset, (uint)exponent.Length);
                WriteToBuffer(ref rsaKey, ref offset, (uint)modulus.Length);
                WriteToBuffer(ref rsaKey, ref offset, primeLen1);
                WriteToBuffer(ref rsaKey, ref offset, primeLen1);
                WriteToBuffer(ref rsaKey, ref offset, exponent);
                WriteToBuffer(ref rsaKey, ref offset, modulus);
                if (primeLen1 != 0)
                {
                    WriteToBuffer(ref rsaKey, ref offset, prime1);
                    WriteToBuffer(ref rsaKey, ref offset, prime2);
                }

                IBuffer rsaBuffer = CryptographicBuffer.CreateFromByteArray(rsaKey);

                if (primeLen1 == 0)
                {
                    cs.Key = rsaProvider.ImportPublicKey(rsaBuffer, CryptographicPublicKeyBlobType.BCryptPublicKey);
                }
                else
                {
                    cs.Key = rsaProvider.ImportKeyPair(rsaBuffer, CryptographicPrivateKeyBlobType.BCryptPrivateKey);
                }
                break;
            }
        case TpmAlgId.Ecc:
            {
                var eccParms = (EccParms)pubKey.parameters;
                var eccPub = (EccPoint)pubKey.unique;
                var algId = RawEccKey.GetEccAlg(pubKey);
                if (algId == null)
                {
                    return null;
                }
                bool isEcdsa = eccParms.scheme.GetUnionSelector() == TpmAlgId.Ecdsa;
                byte[] keyBlob = RawEccKey.GetKeyBlob(eccPub.x, eccPub.y, keyAlgId,
                                                        !isEcdsa, eccParms.curveID);
                AsymmetricKeyAlgorithmProvider eccProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algId);
                cs.Key = eccProvider.ImportKeyPair(CryptographicBuffer.CreateFromByteArray(keyBlob));
                break;
            }
        default:
            Globs.Throw<ArgumentException>("Algorithm not supported");
            cs = null;
            break;
    }
    return cs;
}


来源:https://stackoverflow.com/questions/56263220/how-to-export-public-key-from-tpm-with-tss-net

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!