2016-08-17 5 views
0

У меня проблема с цифровой подписью XML-сообщения. Требования диктуют, что сертификат ECDSA должен использоваться с определенной кривой. Это означает, что функциональность RSA и DSA, предоставляемая методом SignedXml.ComputeSignature(...), не будет работать без создания пользовательской реализации , AsymmetricSignatureFormatter и AsymmetricSignatureDeformatter.Ключ не существует - с помощью самоподписанного сертификата ECDSA

Это, как говорится, и не публикуя много кода. Я создал простую функцию, которая должна принимать сертификат и использовать его открытый ключ для записи данных с использованием класса ECDsaCng, так как это то, что я использовал для создания пользовательской реализации, упомянутой выше ,

Что происходит, даже с моей пользовательской реализацией, я получаю исключение «System.Security.Cryptography.CryptographicException: Key does not exist.». Если, однако, я просто создаю CngKey, а не импортирую его. Из того, что я могу видеть это исключение выгоняют из кода, который вызывает метод на internal static extern ErrorCode NCryptSignHash(...), который находится в ncrypt.dll

Так что мой вопрос, почему исключение «System.Security.Cryptography.CryptographicException: Key does not exist.» и как ее устранить.

[TestMethod] 
public void CreateSignatureTest() 
{ 
    var request = "Some xml goes here..."; 

    var store = new X509Store(StoreLocation.LocalMachine); 
    store.Open(OpenFlags.ReadOnly); 
    var certificates = store.Certificates; 

    var applicableCertificate = certificates.Cast<X509Certificate2>() 
    .FirstOrDefault(certificate => certificate.Subject.Contains("ECDSA_CERT_NAME")); 

    var encryptingKey = (ECDsaCng)applicableCertificate.GetECDsaPublicKey(); 

    var exported = encryptingKey.Key.Export(CngKeyBlobFormat.EccPublicBlob); 
    var creationParameters = new CngKeyCreationParameters 
    { 
    ExportPolicy = CngExportPolicies.AllowPlaintextExport 
    }; 

    using (CngKey objCngKey = CngKey.Import(exported, CngKeyBlobFormat.EccPublicBlob)) // This will throw a Key Does Not Exist Exception 
    //using (CngKey objCngKey = CngKey.Create(CngAlgorithm.ECDsaP256, null, creationParameters)) // This works... 
    { 
    //'Convert String to be signed to a byte array 
    var data = Encoding.Default.GetBytes(request); 

    //'Create a ECDsaCng Object 
    var ecdsa = new ECDsaCng(objCngKey); 

    //'Sign the string 
    var bSignature = ecdsa.SignData(data); 

    //'Convert Signature to Base64 string for better reading 
    var sSignature = Convert.ToBase64String(bSignature); 
    } 
} 

ответ

2

Вы получили открытый ключ. Затем импортировали его в новый контейнер и называли Sign. Поскольку для его подписания требуется секретный ключ, он выдал исключение, указав, что полей закрытого ключа нет.

Почему вы клонируете объект в любом случае? Просто позвоните cert.GetECDsaPrivateKey() и используйте этот объект.

+0

Я пробовал это var encryptingKey = (ECDsaCng) применимоCertificate.GetECDsaPrivateKey(); var exported = ((ECDsaCng) encryptingKey) .Key.Export (CngKeyBlobFormat.EccPrivateBlob); Теперь получите другое исключение. Запрошенная операция не поддерживается. У меня создалось впечатление, что я зашифрую публикацию, и получатель будет проверять секретный ключ? – Geek

+1

Вот как работает шифрование, да; но подписание - наоборот. Подписчик использует закрытый ключ (который у них только есть), верификатор использует публикацию. Но я до сих пор не понимаю, почему вы клонируете объект вообще (что не будет работать для смарт-карты). 'cert.GetECDsaPrivateKey(). SignData (...)' (хотя использование операторов является хорошим) – bartonjs

+0

Последний комментарий был отличным указателем, я вынул клонирование, и теперь я могу подписывать и возвращать подпись. Моя единственная проблема, оставшаяся сейчас, заключается в том, как применить это к пользовательским реализациям SignatureDescription, AsymmetricSignatureFormatter и AsymmetricSignatureDeformatter, чтобы затем создать узел Signature XML. – Geek