Импорт сертификата на основе ECC из хранилища сертификатов Windows в CngKey
Как я могу получить открытые / закрытые ключи от ECC на основе X509Certificate2
в CngKey
для использования с ECDsaCng
а также ECDiffieHellmanCng
?
В настоящее время я использую пары ключей RSA 2048 для подписи / шифрования. Я делаю это, вытягивая сертификаты из X509Store
где они надежно хранятся с закрытыми ключами, помеченными как неэкспортируемые. Я хотел бы преобразовать текущую реализацию для использования ECDSA и ECDH, чтобы я мог использовать ключи меньшего размера для эквивалентной безопасности.
Я успешно сгенерировал сертификаты ECC, используя openssl:
openssl ecparam -out private.pem -name prime256v1 -genkey
openssl req -new -key private.pem -x509 -nodes -days 365 -out public.cer
openssl pkcs12 -export -in public.cer -inkey private.pem -out export.pfx
Я успешно установил выше сгенерированные сертификаты в хранилище сертификатов. Я могу получить их по отпечатку пальца, но провайдеры шифрования для закрытых и открытых ключей выдают исключения "Алгоритм не поддерживается". Вместо этого я понимаю, что должен использовать ECDsaCng
а также ECDiffieHellmanCng
подписать / зашифровать. Но это дело в CngKey
"S.
Надувной замок не вариант, потому что он требует, чтобы закрытые ключи можно было экспортировать.
CLR Security вернет мне CngKey
пара через GetCngPrivateKey
но его нельзя использовать с ECDsa, поскольку ключ, возвращаемый CLRSecurity, является ключом ECDH. Кроме того, CLR Security не дает мне возможность получить только открытый ключ от X509Certificate2
для проверки подписи (где у меня даже нет личного ключа подписавшего).
Есть идеи? Я в своем уме... Любая помощь будет высоко ценится.
1 ответ
Вам необходимо создать CngKey из открытого ключа сертификата:
certificate.PublicKey.EncodedKeyValue.RawData
CngKey содержит 8 дополнительных байтов, первые 4 байта используются для имени используемой кривой (ECS1, ECS3 или ECS5), последние 4 - это длина ключа вкл. набивка (32, 48 или 66).
Первый байт открытого ключа из сертификата удаляется (поскольку для открытого ключа ECDSA это всегда 0x04).
Так, например, для ECDSA с использованием кривой P-256 и алгоритма хеширования SHA-256 вы получите открытый ключ длиной 65 байтов. Откажитесь от первого байта, оставив 64 байта, затем префикс с 4 байтами для кривой и 4 байта для длины ключа, т.е. (Encoding.ASCII):
69 (Е)
67 (С)
83 (с)
49 (1)
32 (длина ключа)
0
0
0
Теперь у вас есть открытый ключ (72 байта) для создания CngKey из:
var cngKey = CngKey.Import ([байтовый массив], CngKeyBlobFormat.EccPublicBlob);
var ecdsaCng = new ECDsaCng (cngKey);
И вы можете проверить подпись:
return ecdsaCng.VerifyData (encodedBytes, подпись);