CNG提供商,如何将EC密钥转换为BCRYPT_ECCKEY_BLOB结构?

时间:2017-07-27 12:16:29

标签: cryptography ecdsa cng

我正在撰写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值似乎也采用了大端格式。

我的问题是:

  1. 'magic'和'length'值是否需要采用big-endian格式?

  2. 如何将大数字X转换为大端格式?转换每个字节?

3 个答案:

答案 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";
} 

您可以使用https://docs.microsoft.com/en-us/sql/advanced-analytics/r/security-considerations-for-the-r-runtime-in-sql-server

在Big-Endian中获取X和Y.