Как экспортировать открытый ключ из TPM с TSS.net? - PullRequest
0 голосов
/ 22 мая 2019

Я получил образец Signing из здесь для запуска с имитатором TPM.

Похоже, у меня есть какая-то ссылка на открытый ключ после вызова:

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); 

Ниже приведен некоторый закомментированный код для этого указания на предыдущий способ экспорта открытого ключа:

// (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);

Кажется, что TpmPublic.GetXml() больше не существует, поэтомувозможно, он был удален согласно примечанию.

1 Ответ

1 голос
/ 25 мая 2019

Не совсем понятно, что вам нужно;какой тип вашего открытого ключа и что вы хотите с ним делать?Таким образом, этот ответ предполагает, что вы пытаетесь получить необработанные байты показателя и модуль открытого ключа RSA, чтобы вы могли экспортировать их в ключ, который затем может быть использован, например, OpenSSL.

Функциональность «экспорта XML», которую вы видели, относится к сериализации и десериализации объекта TpmPublic и на самом деле не приближает вас к вашей цели: вы просто получите исходный объект обратно.Вероятно, он был удален, потому что он работал не очень хорошо.

Предполагая, что keyPublic - это ваш TpmPublic объект, представляющий ключ RSA, чтобы получить показатель, который вы сделаете:

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

И чтобы получить модуль:

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

Чтобы увидеть, как обрабатываются ключи ECC, взгляните на 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;
}
...