我正在撰写CNG提供商。具体而言,坚持实施NCryptExportKey
API。我正在尝试从硬件密钥管理器转换EC密钥(用于签名,ECDSA256)。 h / w keymanager提供ASN格式的密钥。我提到了MSDN文档,提到公钥X和Y值(BCRYPT_ECCKEY_BLOB结构)是big-endian格式。但是在stackoverflow(Import a Public key from somewhere else to CngKey?)的另一篇文章中,Magic值似乎也采用了大端格式。
我的问题是:
'magic'和'length'值是否需要采用big-endian格式?
如何将大数字X转换为大端格式?转换每个字节?
答案 0 :(得分:1)
您可以这样将EC密钥转换为BCRYPT_ECCKEY_BLOB。 我们应该忽略EC密钥的第一个字节,因为它仅表示压缩/未压缩的格式。
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);
现在使用bycrtptKey进行导入。
答案 1 :(得分:0)
魔术用于比较常数。因为它不是一个数字,所以它不是大端或小端格式。您应该只使用常量来设置或比较值;他们不一定需要包含任何数字。
长度是ULONG,因为.NET不幸的是基于小端,它无疑也存储为小端。通常你不在乎;只需使用ULONG即可设置或检索它。
如果你有一个BigInteger
实例,那么你可以使用ToByteArray
将其保存为字节,然后颠倒字节的顺序。里面的位将保持不变。如果该值左侧为零字节(反转后),则还需要删除该字节。
答案 2 :(得分:0)
为了从群组转换为魔法,您可以轻松地执行此操作(伪代码):
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";
}
在Big-Endian中获取X和Y.