Импорт сертификата на основе ECC из хранилища сертификатов Windows в CngKey

Как я могу получить открытые / закрытые ключи от ECC на основе X509Certificate2в CngKeyдля использования с ECDsaCng а также ECDiffieHellmanCng?

В настоящее время я использую пары ключей RSA 2048 для подписи / шифрования. Я делаю это, вытягивая сертификаты из X509Store где они надежно хранятся с закрытыми ключами, помеченными как неэкспортируемые. Я хотел бы преобразовать текущую реализацию для использования ECDSA и ECDH, чтобы я мог использовать ключи меньшего размера для эквивалентной безопасности.

Я успешно сгенерировал сертификаты ECC, используя openssl:

  1. openssl ecparam -out private.pem -name prime256v1 -genkey
  2. openssl req -new -key private.pem -x509 -nodes -days 365 -out public.cer
  3. 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, подпись);

Другие вопросы по тегам