Файл подписи ECDSA с ключом из хранилища C # .Net CNG

Я пытаюсь подписать файл с ECDSA, используя API CNG и сертификат из хранилища сертификатов Microsoft. Я прочитал много документации и почти готов, но зацикливался на импорте секретного ключа из сертификата. Я сделал то же самое с RSA, но, похоже, все по-другому. Вот код, который у меня есть:

<code>    static void signFile()
    {
        X509Certificate2 myCert = 
             selectCert(StoreName.My, 
                        StoreLocation.CurrentUser, 
                        "Select a Certificate",
                        "Please select a certificate from the list below:");

        Console.Write("Path for file to sign: ");
        string path = Console.ReadLine();
        TextReader file = null;
        try
        {
            file = new StreamReader(path);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            Console.Write("\nPress any key to return to the main menu: ");
            Console.ReadKey();
        }
        UnicodeEncoding encoding = new UnicodeEncoding();
        byte[] data = encoding.GetBytes(file.ReadToEnd());
        ECDsaCng dsa = new ECDsaCng(
            CngKey.Import(StringToByteArray(myCert.PrivateKey.ToString()),
                          CngKeyBlobFormat.EccPrivateBlob,
                          CngProvider.MicrosoftSoftwareKeyStorageProvider));

        dsa.HashAlgorithm = CngAlgorithm.Sha384;
        byte[] sig = dsa.SignData(data);
        TextWriter signatureFile = new StreamWriter("signature.txt");
        signatureFile.WriteLine("-----BEGIN SHA384 SIGNATURE-----" + 
                                ByteArrayToString(sig) + 
                                "-----END SHA384 SIGNATURE-----");
        signatureFile.Close();
    }
</code>

И я получаю ошибку

System.NotSupportedException: The certificate key algorithm is not supported.

Мой сертификат ECDSA_P256 sha384ECDSA со следующими расширениями:

<code>Digital Signature, Non-repudiation, independent signing revocation list (CRL), CRL Signing (CRL) (c2)
Server Authentication (1.3.6.1.5.5.7.3.1)
Client Authentication (1.3.6.1.5.5.7.3.2)
Code Signing (1.3.6.1.5.5.7.3.3)
Unknown Key Usage (1.3.6.1.4.1.311.2.1.22)
Unknown Key Usage (1.3.6.1.4.1.311.2.1.21)
IKE-intermediary IP-security (1.3.6.1.5.5.8.2.2)
</code>

Может показаться, что проблема в сертификате, но я не уверен, что это может быть код или нет.

Вот мой сертификат с открытым ключом:

<code>Certificate:
Data:
    Version: 3 (0x2)
    Serial Number: 2 (0x2)
Signature Algorithm: ecdsa-with-SHA384
    Issuer: C=##, O=#######, OU=#####, OU=#####, CN=###########
    Validity
        Not Before: Apr 27 16:35:51 2012 GMT
        Not After : Apr 26 16:35:51 2017 GMT
    Subject: C=##, O=###########, OU=#####, CN=#############
    Subject Public Key Info:
        Public Key Algorithm: id-ecPublicKey
            Public-Key: (256 bit)
            pub:
                04:fc:d5:ce:ad:1f:0c:19:b9:3d:2b:bd:7d:f0:8c:
                44:46:db:e3:42:14:b1:1a:9f:7c:ab:e1:be:ad:a5:
                0c:03:2d:0f:ff:3f:10:d4:69:eb:4c:82:a1:2a:61:
                56:45:03:04:a6:49:f7:16:6e:dd:60:22:c6:20:c5:
                4d:44:49:21:41
            ASN1 OID: prime256v1
    X509v3 extensions:
        X509v3 Key Usage: critical
            Digital Signature, Non Repudiation, CRL Sign
        X509v3 Extended Key Usage: critical
            TLS Web Server Authentication, TLS Web Client Authentication, Co
de Signing, Microsoft Commercial Code Signing, Microsoft Individual Code Signing
, 1.3.6.1.5.5.8.2.2
        X509v3 Authority Key Identifier:
            DirName:/C=##/O=#######/OU=#####/OU=#####/CN=######
            serial:01
        X509v3 Subject Key Identifier:
            B7:A8:F9:55:9A:43:9E:BE:1C:4B:62:52:91:C2:F1:39:72:E1:CE:1B
        X509v3 Basic Constraints: critical
            CA:FALSE
Signature Algorithm: ecdsa-with-SHA384
     30:81:88:02:42:01:75:55:f3:64:f9:aa:2a:66:55:b1:ca:dc:
     86:ac:1f:7d:2a:ec:10:87:db:74:88:0e:77:e3:18:82:15:a7:
     32:91:1a:2d:ea:07:2e:78:8d:dc:8a:18:3c:2b:5a:9b:6a:0f:
     97:f6:f8:8d:c5:fc:0e:9f:20:e9:b0:16:90:1a:c4:58:ac:02:
     42:01:dc:b3:88:ae:44:54:c4:e0:b7:c2:37:88:0b:19:6b:96:
     99:f7:21:12:45:12:21:e5:ab:83:39:a6:47:3a:08:87:b0:fa:
     0e:31:1b:97:83:8d:65:30:a1:43:c1:82:27:77:6e:93:89:1b:
     bd:57:b1:7a:54:9e:cc:e1:44:cc:74:16:c5
</code>
 Maarten Bodewes09 мая 2012 г., 00:22
Microsoft имеет довольно ограниченную поддержку Elliptic Curve Cryptography (ECC). Он обеспечивает только «эллиптическую кривую DSA (ECDSA) поверх стандартных простых кривых NIST P-256, P-384 и P-521». и они должны быть "названы" кривые. Знаете ли вы, какие параметры домена EC находятся в сертификате? В качестве альтернативы вы можете вставить шестнадцатеричный, base64 или ASN.1 текст сертификата, чтобы мы могли это выяснить.
 Андрей25 мая 2012 г., 04:15
Так бы я использовалDSACryptoServiceProvider на самом деле завершить подписание или просто обработать импорт ключа EC? Если бы вы могли предоставить пример кода, я бы хотел окончательно пометить это как решенное. Еще раз спасибо за помощь, кстати.
 Maarten Bodewes10 мая 2012 г., 21:22
Ах, я понимаю, где вы идете не так, надо было надеть мои очки. ToString не кодирует закрытый ключ. Он просто печатает некоторую информацию о закрытом ключе. Вы можете использоватьDSACryptoServiceProvider что свойство PrivateKey фактически расширяется вместо кодирования / перекодирования закрытого ключа.
 Maarten Bodewes10 мая 2012 г., 21:14
Вы можете редактировать свой вопрос вместо ответа, чтобы предоставить больше информации. Перечитав вопрос, сам сертификат не содержит закрытого ключа. Обычно вы создаете пару ключей, создаете запрос сертификата, содержащий открытый ключ, и подписываете его с помощью закрытого ключа. Затем ЦС выпекает из него сертификат и отправляет его обратно. Этот сертификат содержит только открытый ключ. Итак, когда вы пытаетесь импортировать закрытый ключ, в каком формате это? PKCS # 12? Это было бы либо.pkf или же.p12 Расширения файлов.
 Андрей03 июл. 2012 г., 00:16
Кроме того, свойство алгоритма открытого ключа является правильным в соответствии с Целевой группой по Интернет-разработкам (tools.ietf.org/search/rfc3279#page-13) похоже, это проблема Microsoft. Я протестировал образец программы Microsoft (потерял URL), где я столкнулся с той же ошибкой. Кажется, они на самом деле не могут поддерживать ECC в отличие от того, чтоmsdn.microsoft.com/en-us/library/windows/desktop/… говорит

Ответы на вопрос(3)

..6.1 решил основные потребности этой проблемы. Новый код будет

...
byte[] sig;
using (ECDsa ecdsa = cert.GetECDsaPrivateKey())
{
    if (ecdsa == null) throw new Exception("Not an ECDSA cert, or has no private key");

    sig = ecdsa.SignData(data, HashAlgorithmName.SHA384);
}

В ..6.1 также исправлена ошибка, из-за которой некоторые ключи сертификатов возвращаются как ECDH и, таким образом, перестают работать. (Ну, это не решило проблему некоторых закрытых ключей, рассматриваемых как ECDH - которые не имели никакого отношения к EKU аутентификации сервера, но были хорошим предположением - но теперь считают эти ключи действительными).

и у меня были точно такие же проблемы. Мы закончили тем, что создали наши собственные CngKeys с ECDsa_P256 SHA256, но я верю, что я узнал кое-что, копаясь в CryptoApi:

Если у вас есть сертификат, помеченный как «Аутентификация сервера (1.3.6.1.5.5.3.3.1)» & quot; (используйте в качестве SSL-сертификата), ваш сертификат будет содержать алгоритм обмена ключами ECDH. И каким-то образом это "имеет приоритет" над группой алгоритмов ECDsa. Таким образом, вы получите страшный «алгоритм ключа сертификата не поддерживается».

Я провел более часа с Symantec, оглядываясь через плечо, и они не могли решить головоломку, поэтому они отказались от «К сожалению, мы не поддерживаем использование сертификатов SSL для чего-либо, кроме SSL».

Вы можете получить свой личный CngKey из сертификата с CLRSecurity от Codeplex (http://clrsecurity.codeplex.com/). Это дает вашему x509Certificate2 расширение, которое учитывает этот код:

X509Certificate cer = <getyourcertcode>;
CngKey k = cer.GetCngPrivateKey();

Проверьте & quot; k & quot; и увидите, что ваша группа алгоритмов, вероятно, является чем-то другим, чем ожидалось Мой был ECDH ...

Решение, которое я пытаюсь сейчас, - это настроить новый сервер CA, заставить его делать именно то, что я хочу. По сути, это сертификат X509, который используется ТОЛЬКО для подписи кода ...

& quot; Использование ключа X509v3: критическая цифровая подпись & quot; возможно, должно быть разрешено только использование ...

Надеюсь, это поможет кому-то еще :-)

 31 мар. 2014 г., 11:07
Ваш ответ не имеет никакого отношения к сертификатам X509 в сертификационном магазине?
 07 июл. 2015 г., 09:57
БУДЬТЕ ЗДОРОВЫ! Я искал более 4 часов в интернете, чтобы найти, как вытащить чертов ключ из сертификата !! Ваша ссылка на сборку безопасности Codeplex была тем, что я искал !!
 31 мар. 2014 г., 07:58
Посмотрите на мой ответ здесь:stackoverflow.com/questions/10264770/…, Проверьте это следующим образом: using (ECDsaCng ecsdKey = new ECDsaCng (CngKey.Import (key, CngKeyBlobFormat.EccPublicBlob))) {if (ecsdKey.VerifyData (data, signature)) Console.WriteLine (& quot; данные верны & quot;); иначе Console.WriteLine (& quot; Данные плохие & quot;); }
 31 мар. 2014 г., 02:40
Как вы собираетесь создать CngKey из открытого ключа? Эта библиотека CLRSecurity, похоже, не обеспечиваетGetCngPublicKey() расширение. Как я могу проверить подпись ECDsa только с помощью открытого ключа подписавшего в сертификате X509 в хранилище сертификатов?

CngKeyBlobFormat.EccPrivateBlob не поддерживается. Какую ОС вы используете? CngKey.Import генерирует CryptographicException только на некоторых машинах

Ваш ответ на вопрос