Импорт сертификата ECC из хранилища сертификатов Windows в CngKey
Как я могу получить общедоступные/частные ключи из X509Certificate2
на основе ECC в 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
.
Bouncy Castle - это не вариант, потому что для доступа к закрытым ключам требуется экспортировать.
Безопасность CLR вернет мне пару CngKey
через GetCngPrivateKey
, но не может использоваться с ECDsa, потому что ключ, возвращаемый CLRSecurity, является ключом ECDH. Кроме того, CLR Security не дает мне способ получить только открытый ключ из X509Certificate2
для проверки подписи (где у меня даже нет или нет закрытого ключа подписывающего лица).
Любые идеи? Я нахожусь на своем пути... Любая помощь будет очень признательна.
Ответы
Ответ 1
Вам нужно создать CngKey из открытого ключа сертификата:
certificate.PublicKey.EncodedKeyValue.RawDatap >
CngKey содержит 8 дополнительных байтов, первые 4 байта используются для имени используемой кривой (ECS1, ECS3 или ECS5), последние 4 - это длина ключа, вкл. (32, 48 или 66).
Первый байт открытого ключа из сертификата удаляется (так как он всегда равен 0x04 для открытого ключа ECDSA).
Так, например, для ECDSA с использованием кривых P-256 и алгоритма хэша SHA-256 вы получите открытый ключ длиной 65 байт. Отбросьте первый байт, оставив 64 байта, затем префикс с 4 байтами для кривой и 4 байта для длины ключа, т.е. (Encoding.ASCII):
69 (E)
67 (C)
83 (S)
49 (1)
32 (длина ключа)
0
0
0
Теперь у вас есть открытый ключ (72 байта) для создания CngKey из:
var cngKey = CngKey.Import([массив байтов], CngKeyBlobFormat.EccPublicBlob);
var ecdsaCng = new ECDsaCng (cngKey);
И вы можете проверить подпись:
return ecdsaCng.VerifyData(encodedBytes, подпись);