问题
I am writing a CNG provider. Specifically, stuck on implementing NCryptExportKey
API. I am trying to convert an EC key (for signing, ECDSA256) from a hardware key manager. The h/w keymanager provides key in ASN format. I referred to MSDN documentation, it's mentioned that public key X and Y values(of BCRYPT_ECCKEY_BLOB structure) are in big-endian format. But in another post on stackoverflow (Import a Public key from somewhere else to CngKey?), the Magic value also seems to be in big-endian format.
My Questions are:
Are the 'magic' and 'length' values need to be in big-endian format?
How a big number X to be converted to big-endian format? Convert each byte?
回答1:
You convert EC key to BCRYPT_ECCKEY_BLOB by like this. We should ignore the first byte from EC key because it just represent compressed/uncompressed format.
BCRYPT_ECCKEY_BLOB eccBlobHeader;
PCHAR bycrtptKey;
eccBlobHeader.dwMagic = BCRYPT_ECDH_PUBLIC_P384_MAGIC;
eccBlobHeader.cbKey = 48;//size of EC key(without 1st byte)
memcpy(bycrtptKey, &eccBlobHeader, 8);//copying 8bytes header blob
memcpy(bycrtptKey+ 8,publicKeyFromOtherParty+1,publicKeyFromOtherPartySize- 1);
now use bycrtptKey for importing.
回答2:
The magic is used to compare against constants. As it isn't a number it isn't in a big endian or little endian format. You should just use the constants to either set or compare the values; they do not necessarily need to contain any number.
The length is an ULONG and since .NET unfortunately is based on little endian it is undoubtedly also stored as little endian. Normally you don't care; just use an ULONG to set or retrieve it.
If you have a BigInteger
instance then you can simply save it as bytes using ToByteArray
and then reverse the order of the bytes. The bits inside will stay the same. If the value has a zero byte to the left (after reversing) then you need to strip that byte as well.
回答3:
In order to convert from group to magic you can easily do this (pseudo code):
ULONG nid_to_magic_<public|private>_<ecdsa|ecdh> (EC_KEY * eckey) {
int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
switch(nid){
case NID_X9_62_prime256v1:
return BCRYPT_<ECDH | ECDSA>_<PUBLIC | PRIVATE>_P256_MAGIC;
case NID_secp384r1:
return BCRYPT_<ECDH | ECDSA>_<PUBLIC | PRIVATE>_P384_MAGIC;
case NID_secp521r1:
return BCRYPT_<ECDH | ECDSA>_<PUBLIC | PRIVATE>_P521_MAGIC;
//And so on...
}
//Note: it seems that the magic number is more "pedantic than NID";
}
You can get X and Y in Big-Endian using BN_bn2bin()
来源:https://stackoverflow.com/questions/45350583/cng-provider-how-to-convert-an-ec-key-to-bcrypt-ecckey-blob-structure