问题
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