Импорт сертификата 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.RawData​​p >

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, подпись);