【问题标题】:CNG provider, how to convert an EC key to BCRYPT_ECCKEY_BLOB structure?CNG 提供商,如何将 EC 密钥转换为 BCRYPT_ECCKEY_BLOB 结构?
【发布时间】:2017-07-27 12:16:29
【问题描述】:
我正在编写一个 CNG 提供程序。具体来说,坚持实现NCryptExportKey API。我正在尝试从硬件密钥管理器转换 EC 密钥(用于签名,ECDSA256)。硬件密钥管理器提供 ASN 格式的密钥。我参考了 MSDN 文档,提到公钥 X 和 Y 值(BCRYPT_ECCKEY_BLOB 结构)是大端格式。但在另一篇关于 stackoverflow (Import a Public key from somewhere else to CngKey?) 的帖子中,Magic 值似乎也是大端格式。
我的问题是:
'magic' 和 'length' 值是否需要采用大端格式?
如何将大数 X 转换为 big-endian 格式?转换每个字节?
【问题讨论】:
标签:
cryptography
ecdsa
cng
【解决方案1】:
为了从组转换为魔术,您可以轻松地执行此操作(伪代码):
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";
}
您可以使用 BN_bn2bin() 获得 Big-Endian 中的 X 和 Y
【解决方案2】:
您可以通过这样的方式将 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 进行导入。
【解决方案3】:
魔术用于与常量进行比较。因为它不是一个数字,所以它不是大端或小端格式。您应该只使用常量来设置或比较值;它们不一定需要包含任何数字。
长度是 ULONG 并且由于 .NET 不幸的是基于小端,它无疑也存储为小端。通常你不在乎;只需使用 ULONG 来设置或检索它。
如果您有一个BigInteger 实例,那么您可以使用ToByteArray 将其简单地保存为字节,然后颠倒字节的顺序。里面的位将保持不变。如果该值的左侧有一个零字节(反转后),那么您也需要删除该字节。