AlexMAS / GostCryptography

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

Ошибка при использовании с WCF, требующим CryptoPro .NET #18

Closed Bykiev closed 5 years ago

Bykiev commented 5 years ago

Здравствуйте, при использовании вашей библиотеки в проекте, где используется WCF-сервис, требующий CryptoPro.NET, возникает ошибка: Parameter must support GOST R 34.10 algorithm.

Server stack trace: 
   в GostCryptography.Base.GostSignatureFormatter.SetKey(AsymmetricAlgorithm privateKey)
   в System.Security.Cryptography.SignatureDescription.CreateFormatter(AsymmetricAlgorithm key)
   в System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetSignatureFormatter(String algorithm)
   в CryptoPro.Sharpei.IdentityModel.CPX509AsymmetricSecurityKey.GetSignatureFormatter(String algorithm)
   в System.IdentityModel.SignedXml.ComputeSignature(SecurityKey signingKey)
   в System.ServiceModel.Security.WSSecurityOneDotZeroSendSecurityHeader.CreateSupportingSignature(SecurityToken token, SecurityKeyIdentifier identifier, ISecurityElement elementToSign)
   в System.ServiceModel.Security.SendSecurityHeader.SignWithSupportingToken(SecurityToken token, SecurityKeyIdentifierClause identifierClause)
   в System.ServiceModel.Security.SendSecurityHeader.SignWithSupportingTokens()
   в CryptoPro.Sharpei.ServiceModel.CPSendSecurityHeader.SignWithSupportingTokens()
   в System.ServiceModel.Security.SendSecurityHeader.CompleteSecurityApplication()
   в System.ServiceModel.Security.SecurityAppliedMessage.OnWriteMessage(XmlDictionaryWriter writer)
   в System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota)
   в System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
   в System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message, Boolean shouldRecycleBuffer)
   в System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
   в System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
   в System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   в System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
   в System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)
   в System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout)
   в CryptoPro.Sharpei.ServiceModel.CPSecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout)
   в System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)
   в System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout)
   в System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
   в System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
   в System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
   в System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
   в System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
   в System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   в System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   в System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Последовательность работы такая: с помощью вашей библиотеки подписывается XML-файл по ГОСТ 34.10-2012 (длина ключа 256 бит), после чего осуществляется обращение к WCF-сервису. Сообщение успешно подписывается вашей библиотекой, но при обращении к WCF-сервису возникает ошибка. При использовании WCF в отдельном проекте проблема не наблюдается. Если важно, то WCF и подпись - это разные проекты, используется in-process side-by-side execution (основной проект на .NET 3.5, эти проекты на .NET 4.0).

CryptoPro CSP: 4.0.9842 CryptoPro.NET - 1.0.6893

AlexMAS commented 5 years ago

Здравствуйте. Тут проблема в работе GostCryptography и CryptoPro.NET в рамках одного процесса. Оба регистрируют SignatureDescription-ы, которые используются для работы с подписью. По stack trace видно, что GostCryptography оказался последним, кто это сделал, поэтому он в самом начале стека. Отправляемые/получаемые WCF-сообщения подписываются ГОСТ-сертификатом, CryptoPro.NET встраивается в работу шифрования WCF и для поиска подходящего подписчика подсовывает свой экземпляр ключа - CPX509AsymmetricSecurityKey. Из ключа извлекается идентификатор алгоритма, по которому происходит поиск структуры SignatureDescription с информацией о том, кто может подписать сообщение. Этой структурой оказывается последняя зарегистрированная т.е. из GostCryptography, которая ничего не знает про CPX509AsymmetricSecurityKey и выдает исключение о неизвестном ключе.

В общем, я подумаю, что с этим можно сделать. :)

Bykiev commented 5 years ago

@AlexMAS, спасибо большое! Надеюсь, удастся решить этот вопрос.

AlexMAS commented 5 years ago

@Bykiev Здравствуйте. Я добавил обработку, которая должна решить вашу проблему. Исправления сейчас находятся в ветке cryptopronet-integration. Поскольку у меня нет окружения, в котором я мог бы проверить ваш случай, хотел бы попросить вас сделать это.

Для этого нужно склонировать репозиторий и/или переключиться на ветку cryptopronet-integration:

git clone -b cryptopronet-integration https://github.com/AlexMAS/GostCryptography.git

Открыть проект, собрать его и подключить полученную dll к своему проекту.

Если все хорошо, я опубликую новую версию в NuGet, если будут сложности с проверкой или вообще, пишите. :)

Bykiev commented 5 years ago

@AlexMAS, здравствуйте. Спасибо, сейчас проверю!

Bykiev commented 5 years ago

@AlexMAS, проверил, работает. Спасибо! P.s. в проект не был включен файл GostExternalAsymmetricAlgorithm.cs

AlexMAS commented 5 years ago

@Bykiev Спасибо. Файл включил в проект :) исправиления опубликовал в NuGet - v2.0.4. Если проблема решена, предлагаю закрыть задачу. :)

Bykiev commented 5 years ago

@AlexMAS, вы собрали ее под .NET 4.5.2, на 4.0 теперь не будет работать?

AlexMAS commented 5 years ago

@Bykiev Да, вы правы на счет целевой платформы. Собрал пакет v2.0.5 как multi-target (net40 и net452).