Поставщик CNG, как преобразовать ключ EC в структуру BCRYPT_ECCKEY_BLOB?
Я пишу провайдер CNG. В частности, застрял на реализации NCryptExportKey
API. Я пытаюсь преобразовать ключ EC (для подписи, ECDSA256) из аппаратного диспетчера ключей. H /w keymanager предоставляет ключ в формате ASN. Я ссылался на документацию MSDN, упоминалось, что значения X и Y открытого ключа (в структуре BCRYPT_ECCKEY_BLOB) представлены в формате с прямым порядком байтов. Но в другом посте о stackru ( импортировать открытый ключ откуда-то еще в CngKey?) Значение Magic также представляется в формате с прямым порядком байтов.
Мои вопросы:
Должны ли значения 'magic' и 'length' быть в формате с прямым порядком байтов?
Как большое число X будет преобразовано в формат с прямым порядком байтов? Конвертировать каждый байт?
2 ответа
Чтобы преобразовать группу в магию, вы можете легко сделать это (псевдокод):
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";
}
Вы можете получить X и Y в Big-Endian, используя BN_bn2bin()
Вы конвертируете ключ 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 для импорта.
Магия используется для сравнения с константами. Поскольку это не число, оно не в формате с прямым или прямым порядком байтов. Вы должны просто использовать константы для установки или сравнения значений; они не обязательно должны содержать любое число.
Длина ULONG и, к сожалению,.NET основана на порядке с прямым порядком байтов, она, несомненно, также хранится как последовательность с прямым порядком байтов. Обычно тебе все равно; просто используйте ULONG, чтобы установить или получить его.
Если у тебя есть BigInteger
экземпляр, то вы можете просто сохранить его как байты, используя ToByteArray
и затем обратный порядок байтов. Биты внутри останутся прежними. Если значение имеет нулевой байт слева (после реверса), то вам также необходимо удалить этот байт.