AlexMAS / GostCryptography

.NET driver for ViPNet CSP and CryptoPro CSP
MIT License
128 stars 41 forks source link

Подпись сообщений в веб-приложении (IIS) #35

Closed Bykiev closed 1 year ago

Bykiev commented 3 years ago

@AlexMAS, здравствуйте!

Нужно подписать сообщение по ГОСТу на стороне сервера в веб-приложении, которое хостится в IIS. Токен воткнут в сервер, личный сертификат установлен в хранилище личных сертификатов компьютера. При вызове метода SetSigningCertificate возникает NullReferenceException. Не подскажете, с чем может быть связана проблема и как ее решить?

{"Message":"An error has occurred.","ExceptionMessage":"Ссылка на объект не указывает на экземпляр объекта.","ExceptionType":"System.NullReferenceException","StackTrace":" в System.Security.Cryptography.X509Certificates.X509CertificateHelper.GetPrivateKeyAlgorithm(X509Certificate2 certificate)\r\n в GostCryptography.Xml.GostSignedXml.SetSigningCertificate(X509Certificate2 certificate)\r\n

Upd: при импорте с закрытым ключом проблема не наблюдается Upd2: Включение взаимодействия с рабочим столом проблему не решило

AlexMAS commented 3 years ago

Здравствуйте. Складывается впечатление, что при вызове SetSigningCertificate() вы передаёте null вместо сертификата (возможно, нужно проверить логику поиска сертификата), либо сертификат без приватного ключа. Если вы хотите подписать сообщение публичным ключом, то попробуйте установить:

GostSignedXml.SigningKey = certificate.GetPublicKeyAlgorithm()

вместо вызова SetSigningCertificate().

Bykiev commented 3 years ago

Спасибо, в метод SetSigningCertificate() точно передается сертификат, но приватный ключ находится на usb-токене. При использовании GostSignedXml.SigningKey = certificate.GetPublicKeyAlgorithm() при вычислении подписи (SignedXml.ComputeSignature()) возникает другая ошибка:

{"Message":"An error has occurred.","ExceptionMessage":"Object contains only the public half of a key pair. A private key must also be provided.","ExceptionType":"System.Security.Cryptography.CryptographicException","StackTrace":" в GostCryptography.Gost_R3410.Gost_R3410_AsymmetricAlgorithm2.SignHash(Byte[] hash)\r\n в GostCryptography.Gost_R3410.Gost_R3410_AsymmetricAlgorithm2.CreateSignature(Byte[] hash)\r\n в GostCryptography.Base.GostSignatureFormatter.CreateSignature(Byte[] hash)\r\n в System.Security.Cryptography.AsymmetricSignatureFormatter.CreateSignature(HashAlgorithm hash)\r\n в System.Security.Cryptography.Xml.SignedXml.ComputeSignature()\r\n в CryptoPro.Sharpei.Xml.CPSignedXmlDetour.ComputeSignature()\r\

Upd: если закрытый ключ импортирован в хранилище реестр, то возникает ошибка "Поставщику не удалось выполнить действие, так как запрошено выполнение в автоматическом контексте.", если закрытый ключ импортирован в хранилище Диск, то документ подписывается

AlexMAS commented 3 years ago

Да, действительно, публичный ключ тут не подойдет. Вам нужно каким-то образом из USB-токена достать экземпляр приватного ключа и передать его в GostSignedXml.SigningKey. Как достать сертификат (приватный ключ) с USB-токена, подсказать не могу.

P.s. В вашем stack-trace фигурирует CryptoPro.Sharpei. Видимо, он установлен на вашей машине. Возможно, он будте конфликтовать с частью функциональности GostCryptography.

Bykiev commented 3 years ago

Спасибо, буду изучать дальше!

Bykiev commented 1 year ago

Проблема наблюдается только в случаях, когда сертификат установлен в хранилище компьютера. Для корректной работы нужно предоставить доступ к закрытому ключу, инструкция здесь: https://dss.cryptopro.ru/docs/adminguide/servicecertificates/privatekeyaccess.html