Git Product home page Git Product logo

gostcryptography's Introduction

GostCryptography

.NET driver for ViPNet CSP and CryptoPro CSP. Implements crypto algorithms based on Russian national cryptographic standards GOST 28147-89, GOST R 34.10 and GOST R 34.11. Also provides abstractions to sign and verify CMS/PKCS #7 messages, sign, verify and encrypt XML documents.

Implemented Algorithms

Tested On

  • Windows 10 x64, CryptoPro CSP 4.0.9963
  • Windows 10 x64, ViPNet CSP 4.2.8.51670

Build instructions

To build package run in repository root:

dotnet build --configuration Release

gostcryptography's People

Contributors

alexmas avatar buldo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gostcryptography's Issues

Ошибка подписания при работе с КриптоПРО

Происходи ошибка:
System.Security.Cryptography.CryptographicException: Error occurred during a cryptographic operation.
в CryptoApiHelper.SignValue(SafeProvHandleImpl providerHandle, SafeHashHandleImpl hashHandle, Int32 keyNumber, Byte[] hashValue)
Конкретно при вычислении размера подписи, в этом кусочке:

        if (!CryptoApi.CryptSignHash(hashHandle, (uint)keyNumber, null, 0, null, ref signatureLength))
        {
            throw CreateWin32Error();
        }

Часто повторяется, в чем может быть проблема?

Верефикация нескольких сигнатур в файле

День добрый.
Имеется примерно следующий файл

<soap:Envelope
	xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
	<soap:Body>
		<ns2:GetResponseResponse
			xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.2"
			xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.2"
			xmlns:ns3="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/faults/1.2">
			<ns2:ResponseMessage>
				<ns2:Response Id="SIGNED_BY_SMEV">
					...
					<ns2:SenderInformationSystemSignature>
						<Signature:Signature
							xmlns:Signature="http://www.w3.org/2000/09/xmldsig#"
							xmlns="http://www.w3.org/2000/09/xmldsig#" Id="">
							<SignedInfo>
								<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
								<SignatureMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256" />
								<Reference Id="" URI="">
									<Transforms>
										<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
										<Transform Algorithm="urn://smev-gov-ru/xmldsig/transform" />
									</Transforms>
									<DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256" />
									<DigestValue>...</DigestValue>
								</Reference>
							</SignedInfo>
							<SignatureValue>...</SignatureValue>
							<KeyInfo Id="">
								<X509Data>
									<X509Certificate>Серт_1</X509Certificate>
								</X509Data>
							</KeyInfo>
						</Signature:Signature>
					</ns2:SenderInformationSystemSignature>
				</ns2:Response>
				<ns2:SMEVSignature>
					<ds:Signature
						xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
						<ds:SignedInfo>
							...
						</ds:SignedInfo>
						<ds:SignatureValue>...</ds:SignatureValue>
						<ds:KeyInfo>
							<ds:X509Data>
								<ds:X509Certificate>Серт_2</ds:X509Certificate>
							</ds:X509Data>
						</ds:KeyInfo>
					</ds:Signature>
				</ns2:SMEVSignature>
			</ns2:ResponseMessage>
		</ns2:GetResponseResponse>
	</soap:Body>
</soap:Envelope>

Который хранит в себе два сертификата.

Вопрос: как проверить эти оба сертефиката на виладность?

Моя попытка:
При проверке сигнатуры вторая сигнатура выдает false
Код метода verify

XmlDocument signedSmevRequest = CreateSmevRequest(xml);

GostSignedXml signedXml = new GostSignedXml(signedSmevRequest) { GetIdElementHandler = GetSmevIdElement };
bool isValid = signedSmevRequest.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#")
	.OfType<XmlElement>()
	.ToArray()
	.All(e =>
	{
		//workaround - remove the signature element here.
		e.ParentNode?.RemoveChild(e);
		signedXml.LoadXml(e);
		XmlNodeList references = signedXml.KeyInfo.GetXml().GetElementsByTagName("X509Certificate");
		X509Certificate2 certificate = new X509Certificate2(Convert.FromBase64String(references[0].InnerText));
		bool valid = signedXml.CheckSignature(certificate.GetPublicKeyAlgorithm());
		return valid;
	});
return isValid;

СМЭВ 3.0

В связи с выходом новой версии СМЭВ было бы неплохо обновить SmevExample.xml SignedXmlSmevTest.cs в GostCryptography.Tests

Exception:«Неправильный открытый ключ поставщика.»

Здравствуйте. Использую библиотеку для подписи XML документов в формате сообщений PKCS #7.
И всё прекрасно работало, пока в качестве криптотокена использовалась джакарта. Но руководство купило ключи на рутокене и, как это обычно бывает, всё поломалось.
Исключение: «Неправильный открытый ключ поставщика.»
в System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner signer, Boolean silent)
Код:
ContentInfo content = new ContentInfo(message);
SignedCms signedCms = new SignedCms(content, false);
CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, certificate);
signer.IncludeOption = X509IncludeOption.EndCertOnly;
//signer.DigestAlgorithm = new Oid("1.2.643.2.2.9", "ГОСТ Р 34.11-94");
signedCms.ComputeSignature(signer);
return signedCms.Encode();
Исключение появляется в момент выполнения ComputeSignature(). Криптопровайдер VipNet.CSP.
Исправить проблему мне не удается. Возможно, Вы сможете мне подсказать, в какую сторону «думать». Спасибо.

2.0.2 + ГОСТ-2001

здравствуйте, Александр! очень благодарен вам за такую библиотеку, особенно за примеры кода к ней!
мой проект - реализация взаимодействия с ФСС по ЭЛН со стороны медицинских организаций.
(https://cabinets-test.fss.ru/eln.html)
у меня появились трудности её применения при переходе на новый ГОСТ и новую версию вашей разработки.

  1. При шифровании запроса публичным ключом уполномоченного лица ФСС ГОСТ2012 - в ответ приходит ошибка о невозможности расшифровать. При использовании для шифрования сертификата уполн.лица фсс с ГОСТ2001 - проходит нормально. Этот вопрос ещё задам в ФСС.
  2. При использовании для формирования подписи (врача или МО) сертификата ГОСТ2001 - на вызове GostCryptography.Xml.GostSignedXmlImpl.ComputeSignatureGost() получаю ошибку "System.Security.Cryptography.CryptographicException: Ошибка исполнения функции.".2parse_2019-01-30T07-24-37--5796.log Если использовать ГОСТ2012 - подпись формируется и при отправке принимается сервисом.

Ошибка импорта сессионного ключа в Windows 10, 2012R2, 2016

В Windows 10, 2012R2, 2016 не работают примеры для шифрования/расшифрования данных с передачей сессионного ключа. Например, EncryptDecryptSessionKeyTest.
При попытке расшифровать сессионный ключ функция CryptoApi.CryptImportKey выдает ошибку "Плохой ключ" (для VipNet) или "Плохие данные" (для КриптоПро).
Stacktrace:

 в GostCryptography.Native.CryptoApiHelper.ImportCspBlob(Byte[] importedKeyBytes, SafeProvHandleImpl providerHandle, SafeKeyHandleImpl publicKeyHandle, SafeKeyHandleImpl& keyExchangeHandle) в \Source\GostCryptography\Native\CryptoApiHelper.cs:строка 905
   в GostCryptography.Native.CryptoApiHelper.ImportKeyExchange(SafeProvHandleImpl providerHandle, GostKeyExchangeInfo keyExchangeInfo, SafeKeyHandleImpl keyExchangeHandle) в \Source\GostCryptography\Native\CryptoApiHelper.cs:строка 958
   в GostCryptography.Cryptography.GostKeyExchangeAlgorithm.DecodeKeyExchangeInternal(Byte[] encodedKeyExchangeData, Int32 keyExchangeExportAlgId) в \Source\GostCryptography\Cryptography\GostKeyExchangeAlgorithm.cs:строка 150

Сессионный ключ как-то некорректно передается...
Т.е. не удается расшифровать зашифрованные данные на той же самой машине тем же самым процессом. Не удается также расшифровать эти данные и на других машинах, например, под Windows 7.
При этом в Windows 7 шифрование работает корректно на тех же самых сертификатах, данные шифруются корректно. Примеры успешно работают.
В чем может быть проблема?

Создание симметричных ключей для тестов

Добрый день.

Пробую реализовать обмен пакетами содержащими имитовставки.
Подскажите, пожалуйста, как можно расшарить симметричный ключ между двумя сервисами для тестов? Аналогично вот этому коду?

                public void ShouldComputeHMAC(ProviderType providerType)
		{
			// Given
			var dataStream = CreateDataStream();
			var sharedKey = new Gost_28147_89_SymmetricAlgorithm(providerType);

			// When
			var hmacDataStream = CreateHmacDataStream(sharedKey, dataStream);
			var isValidHmacDataStream = VerifyHmacDataStream(sharedKey, hmacDataStream);

			// Then
			Assert.IsTrue(isValidHmacDataStream);
		}

К сожалению- не имею совершенно не имею опыта в криптографии.

Интеграция с ФСС

Добрый день, подскажите есть пример шифрования запроса на сервис ФСС под ГОСТ 2012

Алгоритм ключа сертификата не поддерживается

var publicKey = (GostAsymmetricAlgorithm)certificate.GetPublicKeyAlgorithm(); - когда я попытался взять public key возваращает ошибку {"Алгоритм ключа сертификата не поддерживается."}
В моем ключе

Publickey.Oid: {
Value: "1.2.398.3.10.1.1.1.1"
FriendlyName: "ГОСТ 34.310-2004."
}

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

.netcore

КриптопроCSP установдлен
Сертификат корректный (но privateKey свойство у него недоступно почему-то), но при попытке подписать сообщение ниже приведенным кодом возникает ошибка:
GostCryptoConfig.ProviderType = GostCryptography.Base.ProviderType.CryptoPro_2012_512;

        //Создание объекта для подписи сообщения
        var signedCms = new GostSignedCms(new ContentInfo(message),true);
        
       
        // Создание объект с информацией о подписчике           
        var signer = new CmsSigner(certificate);
        
        var tt = certificate.GetHashAlgorithm();
        //signer.DigestAlgorithm = Oid.FromOidValue("1.2.643.7.1.1.2.2", OidGroup.HashAlgorithm); //GostCryptography.Asn1.Gost.Gost_R3410_2012_256.Gost_R3410_2012_256_Constants.HashAlgorithm.ToOid();
         // Включение информации только о конечном сертификате (только для теста)
         signer.IncludeOption = X509IncludeOption.EndCertOnly;
         
         // Создание подписи для сообщения CMS/PKCS#7
         signedCms.ComputeSignature(signer);

Ошибка:
'1.2.643.7.1.1.2.2' is not a known hash algorithm.
trace:
at Internal.Cryptography.PkcsHelpers.GetDigestAlgorithm(String oidValue, Boolean forVerification)
at System.Security.Cryptography.Pkcs.CmsSigner.Sign(ReadOnlyMemory`1 data, String contentTypeOid, Boolean silent, X509Certificate2Collection& chainCerts)
at System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner signer, Boolean silent)
at GostCryptography.Pkcs.GostSignedCms.ComputeSignature(CmsSigner signer, Boolean silent)
at GostCryptography.Pkcs.GostSignedCms.ComputeSignature(CmsSigner signer)

Что я делаю неверно?

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

@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: Включение взаимодействия с рабочим столом проблему не решило

Дешифрация на стороне сервиса

Здравствуйте, Александр.
Пробую использовать вашу библиотеку в сервисе на IIS.
При дешифрации использовал пример из https://github.com/AlexMAS/GostCryptography/tree/master/Source/GostCryptography.Tests

var encryptedXml= new GostEncryptedXml(doc);
encryptedXml.AddKeyNameMapping("KeyName1", privateKey); /* Добавляю ссылку на приватный ассиметричный ключ с установленным privateKey.SetContainerPassword(secureString); /
encryptedXml.DecryptDocument(); /
Но на этапе дешифровки криптопровайдер всё равно запрашивает выводит окно для указания пароля для сертификата */

Возможно ли установить пароль для контейнера сертификата программно без вывода на экран окна криптопровайдера при дешифрации (сертификаты находятся в локальном хранилище компьютера)?

Smev.Verify. Обнаружено неизвестное преобразование.

Здравствуйте.

Для метода Sign реализовали кастомную трансорфмацию:
<ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform" />
И все работает хорошо...
Но когда пытаемся реализовать метод Verify, то ловим исключение

Код (взят из тестов)

GostSignedXml signedXml = new GostSignedXml(signedSmevRequest) {GetIdElementHandler = GetSmevIdElement};
XmlNodeList nodeList = signedSmevRequest.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl);
XmlNode node = nodeList[0];
XmlElement el = node as XmlElement;

//крашится на этом моменте
signedXml.LoadXml(el);

Исключение

System.Security.Cryptography.CryptographicException: Обнаружено неизвестное преобразование.
   в System.Security.Cryptography.Xml.Reference.LoadXml(XmlElement value)
   в System.Security.Cryptography.Xml.SignedInfo.LoadXml(XmlElement value)
   в System.Security.Cryptography.Xml.Signature.LoadXml(XmlElement value)
   в System.Security.Cryptography.Xml.SignedXml.LoadXml(XmlElement value)
   в GostCryptography.Xml.GostSignedXml.LoadXml(XmlElement element)

XML файл на выходе с метода Sign имеет следующую структуру

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
	<soap:Body>
		<ns2:SendRequestResponse xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.2" xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.2" xmlns:ns3="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/faults/1.2">
			<ns2:MessageMetadata Id="SIGNED">
				<ns2:MessageId></ns2:MessageId>
				<ns2:MessageType></ns2:MessageType>
				<ns2:Sender>
					<ns2:Mnemonic></ns2:Mnemonic>
				</ns2:Sender>
				<ns2:SendingTimestamp></ns2:SendingTimestamp>
				<ns2:Recipient>
					<ns2:Mnemonic></ns2:Mnemonic>
				</ns2:Recipient>
				<ns2:Status></ns2:Status>
			</ns2:MessageMetadata>
			<ns2:SMEVSignature>
				<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
					<ds:SignedInfo>
						<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
						<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411" />
						<ds:Reference URI="#SIGNED">
							<ds:Transforms>
								<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
								<ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform" />
							</ds:Transforms>
							<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411" />
							<ds:DigestValue></ds:DigestValue>
						</ds:Reference>
					</ds:SignedInfo>
					<ds:SignatureValue></ds:SignatureValue>
					<ds:KeyInfo>
						<ds:X509Data>
							<ds:X509Certificate></ds:X509Certificate>
						</ds:X509Data>
					</ds:KeyInfo>
				</ds:Signature>
			</ns2:SMEVSignature>
		</ns2:SendRequestResponse>
	</soap:Body>
</soap:Envelope>

Опытным путем было выяснено, что ошибка появляется только если есть
<ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform" />

Как решить данную проблему с кастомной трансофрмацией?

Нет возможности указать пароль контейнера закрытого ключа при создании открепленной подписи

Использую GostCryptography, для создания открепленной (CMS Sign, PKCS7) подписи. Пользуюсь примером из тестового проекта "SignedCmsSignTest", идущего вместе с исходниками. Никак не получается программно указать пароль контейнера VipNet для создания автоматизации ЦП. Для обычного шифрования/подписи данных проблем не возникает, но в случае создания открепленной подписи, в классах GostSignedCms и NET CmsSigner нет возможности указать пароль контейнера приватного ключа или Алгоритм подписи с уже заданным ключом.

Даже когда использую конструктор public CmsSigner (CspParameters parameters) и в CspParameters, заполненным параметрами из сертификата добавляю SecureString с необходимым паролем и флагом подавления окна cspKeyParams.Flags = CspProviderFlags.NoPromp - все равно во время выполнения VipNet вываливает диалоговое окно с предложением ввести пароль контейнера.

var cspKeyParams = certificate.GetPrivateKeyInfo();
cspKeyParams.Flags = CspProviderFlags.NoPrompt;
cspKeyParams.KeyPassword = secStr;
var signer = new CmsSigner(cspKeyParams);

Судя по исходникам NET эти два параметра CspParameters просто игнорируются в недрах класса CmsSigner.
Можно ли добавить какую-либо возможность использовать в библиотеке пароль контейнера в данном случае?
P.S. Спасибо за библиотеку!

Проблема(?) с настройками по-умолчанию

И снова приветствую!

Не уверен, что это баг, но с виду выглядит, что так.
Последовал данному в другом вопросе совету и убрал передачу типа провайдера в конструкторы алгоритмов. Использую соответствующие свойства GostCryptoConfig.

И тут вдруг выяснилось, что сломалось шифрование на сертификат ФСС, выпущенный по новым ГОСТам. Лечится это явной передачей CryptoPro_2012_512 в конструктор Gost_28147_89_SymmetricAlgorithm. Решил посмотреть, что происходит по-умолчанию и дошёл вот до этого куска:

protected GostSymmetricAlgorithm() : this(GostCryptoConfig.ProviderType)
{
}

Но ведь если шифрование идёт на новый ГОСТ, то надо брать значение не из ProviderType, а из ProviderType_2012_5121 или ProviderType_2012_1024. Не знаю, можно ли с этим что-то сделать, но поведение странное.

SignatureDescription could not be created for the signature algorithm supplied

Добрый день!

При подписании XML и указания
SignedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"
возникает ошибка

System.Security.Cryptography.CryptographicException: SignatureDescription could not be created for the signature algorithm supplied

А при указании SignedXml.SignedInfo.SignatureMethod = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102001-gostr3411"

ругается проверка СМЭВ:

The requested algorithm urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102001-gostr3411 does not exist. Original Message was: null

Что я делаю не так?)

Ожидания СМЭВ:

	<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
		<ds:SignedInfo>
			<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
			<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411" />
			<ds:Reference URI="#PERSONAL_SIGNATURE">
				<ds:Transforms>
					<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
					<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411" />
				<ds:DigestValue/>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue/>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate/>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>

Реальность, которая у меня получилась:

	<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
		<SignedInfo>
			<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
			<SignatureMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102001-gostr3411" />
			<Reference URI="#PERSONAL_SIGNATURE">
				<Transforms>
					<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
					<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
				</Transforms>
				<DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411" />
				<DigestValue/>
			</Reference>
		</SignedInfo>
		<SignatureValue/>
		<KeyInfo>
			<X509Data>
				<X509Certificate/>
			</X509Data>
		</KeyInfo>
	</Signature>

Создание сессионного ключа. Ошибка плохой ключ.

Добрый день.
Пишу такой код

static void Main(string[] args)
        {
            
            X509Store x509CertificateStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            X509Certificate2Collection x509Certificate2Collection = null;
            X509Certificate2 fssCertificate;
           
            x509CertificateStore.Open(OpenFlags.ReadOnly);
            x509Certificate2Collection = x509CertificateStore.Certificates.Find(X509FindType.FindBySerialNumber, "00c4750d5b11e4db80e811f4cab74fa01e", false);
            if (x509Certificate2Collection.Count == 1)
            {
                fssCertificate = new X509Certificate2(x509Certificate2Collection[0]);
            }
            else
            {
                fssCertificate = null;
            }
            try
            {
                using (var sessionKey = new Gost_28147_89_SymmetricAlgorithm(ProviderType.CryptoPro_2012_512))
                {
                    var publicKey = (GostAsymmetricAlgorithm)fssCertificate.GetPublicKeyAlgorithm();

                    byte[] encryptedKey = GostEncryptedXml.EncryptKey(sessionKey, publicKey);
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
                        
            
            Console.ReadKey();
        }

Получаю ошибку System.Security.Cryptography.CryptographicException: "Плохой ключ."
Сертификат беру отсюда
https://lk.fss.ru/FSS_PROD_CERT_2019_34.10-2012.cer

Использую алгоритм ГОСТ 34.10.2012
Крипртопровайдер крипто про CSP 4.0.9963

Подскажите, что я делаю неправильно.
Спасибо за помощь.

Использование в госорганах

Александр, интересует вопрос относительно необходимости сертификации вашего ПО в госорганах.

Я правильно понимаю, что ваш .Net-провайдер использует исключительно интерфейс Microsoft CryptoAPI и через него обращается к крипто-провайдеру КриптоПро CSP или ViPNet CSP? Реализации самих алгоритмов шифрования в GostCryptography нет?

Таким образом, сертификация ФСТЭК не требуется? Или какие-то алгоритмы криптозащиты всё же есть в библиотеке?

Недопустимый тип криптографического сообщения.

Добрый день. Для работы требуется установленное КриптоПРО CSP на ПК, или вся информация об OID и ключах шифрования тут имеется?
Пытаюсь декодировать зашифрованный файл с подписью:
GostSignedCms gostSignedCms = new GostSignedCms();
gostSignedCms.Decode(fileName);

Получаю ошибку: "System.Security.Cryptography.CryptographicException: Недопустимый тип криптографического сообщения."

С установленным криптопро csp и стандартным классом .net EnvelopedCms все удается сделать. Но имеется необходимость сделать реализацию без установленного криптопро, чтобы можно было опубликовать приложение в вэб, без установленного криптопро, в котором имеется вся информация по алгоритмам шифрования: https://cpdn.cryptopro.ru/content/csp40/html/group___pro_c_s_p_ex_DP8.html

Расшифровка с помощью сертификата

Здравствуйте!
Имеется сертификат и закрытый ключ к нему. Как расшифровать строку, зашифрованную этим сертификатом? Ассиметричное шифрование подразумевает, что шифруется открытым ключом, а расшифровывается закрытым. Пробовал делать разными способами с помощью Вашей библиотеки, но результат один и тот же - ошибка

ASN.1 encoded byte array contains invalid structure 'Gost_R3410_KeyTransport'

Один из способов:

public static byte[] DecryptKey(string encDataInbase64, X509Certificate2 cert)
{
    Gost_R3410_2012_256_AsymmetricAlgorithm assymAlgorithm = cert.GetPrivateKeyAlgorithm() as 
    Gost_R3410_2012_256_AsymmetricAlgorithm;
    SymmetricAlgorithm sessionKey = GostEncryptedXml.DecryptKey(Convert.FromBase64String(encDataInbase64), assymAlgorithm);
    return sessionKey.Key;
}

Пожалуйста, подскажите, что я делаю не так?
PS: расшифровка нужна на этапе 2 аутентификации по руководству https://docs-ke.readthedocs.io/ru/latest/auth/%D0%BF%D0%BE%20%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D1%83.html

Поддержка префиксов в xmldsig

Доброго дня!

Спасибо за продукт! Очень выручаете!

Хотел попросить рассмотреть возможность поддержки работы с префиксом на блок Signature лично столкнулся с проблемой на примере сервиса ГИИС ДМДК https://dmdk.ru они отступают от стандарта и требуют префикс причем только "ds" пока решил временным костылём но хочется видеть интегрированное в библиотеку, более изящное и лаконичное решение так как не имею опыта работы с xml прикладываю то, что у меня работает.

Работающий код:

`
public static void SignDmdkXml(string requestFileName, string requestSignedFileName,
X509Certificate2 certificate, bool saveFormat = true)
{
// Подгружаем документ
var xdoc = new XmlDocument
{
PreserveWhitespace = saveFormat
};

            xdoc.Load(requestFileName);

            // Создание подписчика XML-документа
            var signedXml = new PrefixedSignedXml(xdoc,"ds")
            {
                // Установка ключа для создания подписи
                SigningKey = certificate.PrivateKey,
                SignedInfo =
                {
                    // Установка алгоритма нормализации узла SignedInfo (в соответствии с методическими рекомендациями СМЭВ)
                    CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl,
                    // Установка алгоритма хэширования (в соответствии с методическими рекомендациями СМЭВ)
                    SignatureMethod = CPSignedXml.XmlDsigGost3410_2012_256Url
                }
            };

            // Ссылка на узел, который нужно подписать, с указанием алгоритма хэширования
            var dataReference = new Reference
            {
                Uri = "#body",
                DigestMethod = CPSignedXml.XmlDsigGost3411_2012_256Url
            };

            // Метод преобразования, применяемый к данным перед их подписью (в соответствии с методическими рекомендациями СМЭВ)
            dataReference.AddTransform(new XmlDsigExcC14NTransform());
            dataReference.AddTransform(new XmlDsigSmevTransform());

            signedXml.SafeCanonicalizationMethods.Add("urn://smev-gov-ru/xmldsig/transform");

            // Установка ссылки на узел
            signedXml.AddReference(dataReference);

            // Установка информации о сертификате, который использовался для создания подписи
            var keyInfo = new KeyInfo();
            keyInfo.AddClause(new KeyInfoX509Data(certificate));
            signedXml.KeyInfo = keyInfo;

            // Вычисление подписи
            signedXml.ComputeSignature();

            // Получение XML-представления подписи
            var signatureXml = signedXml.GetXml();

            //// Добавление подписи в исходный документ
            xdoc.GetElementsByTagName("ns:CallerSignature")[0].AppendChild(xdoc.ImportNode(signatureXml, true));

            // Охраняем документ в выходной файл
            if (!saveFormat)
            {
                var settings = new XmlWriterSettings
                {
                    Indent = false,
                    NewLineChars = Empty
                };

                using var writer = XmlWriter.Create(requestSignedFileName, settings);
                xdoc.Save(writer);
            }
            else
                xdoc.Save(requestSignedFileName);
        }
    }

`

Использую обвертку над XmlSigned:

`
///


/// Thx https://stackoverflow.com/a/12343267
///

public class PrefixedSignedXml : SignedXml
{
private readonly string _prefix;

    public PrefixedSignedXml(XmlDocument document, string prefix)
        : base(document)
    {
        _prefix = prefix;
    }

    public void ComputeSignature()
    {
        BuildDigestedReferences();
        var signingKey = SigningKey;
        if (signingKey == null)
        {
            throw new CryptographicException("Cryptography_Xml_LoadKeyFailed");
        }
        if (SignedInfo.SignatureMethod == null)
        {
            if (signingKey is not DSA)
            {
                if (signingKey is not RSA)
                {
                    throw new CryptographicException("Cryptography_Xml_CreatedKeyFailed");
                }

                SignedInfo.SignatureMethod ??= "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
            }
            else
            {
                SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
            }
        }

        if (CryptoConfig.CreateFromName(SignedInfo.SignatureMethod) is not SignatureDescription description)
        {
            throw new CryptographicException("Cryptography_Xml_SignatureDescriptionNotCreated");
        }
        var hash = description.CreateDigest();
        if (hash == null)
        {
            throw new CryptographicException("Cryptography_Xml_CreateHashAlgorithmFailed");
        }
        GetC14NDigest(hash, _prefix);
        m_signature.SignatureValue = description.CreateFormatter(signingKey).CreateSignature(hash);
    }

    public new XmlElement GetXml()
    {
        var e = base.GetXml();
        SetPrefix(_prefix, e);
        return e;
    }

    //Отражательно вызывать закрытый метод SignedXml.BuildDigestedReferences
    private void BuildDigestedReferences()
    {
        var t = typeof(SignedXml);
        var m = t.GetMethod("BuildDigestedReferences", BindingFlags.NonPublic | BindingFlags.Instance);
        m?.Invoke(this, new object[] { });
    }

    private void GetC14NDigest(HashAlgorithm hash, string prefix)
    {
        //string securityUrl = (this.m_containingDocument == null) ? null : this.m_containingDocument.BaseURI;
        //XmlResolver xmlResolver = new XmlSecureResolver(new XmlUrlResolver(), securityUrl);
        var document = new XmlDocument
        {
            PreserveWhitespace = true
        };
        var e = SignedInfo.GetXml();
        document.AppendChild(document.ImportNode(e, true));
        //CanonicalXmlNodeList namespaces = (this.m_context == null) ? null : Utils.GetPropagatedAttributes(this.m_context);
        //Utils.AddNamespaces(document.DocumentElement, namespaces);

        var canonicalizationMethodObject = SignedInfo.CanonicalizationMethodObject;
        //canonicalizationMethodObject.Resolver = xmlResolver;
        //canonicalizationMethodObject.BaseURI = securityUrl;
        SetPrefix(prefix, document.DocumentElement); //мы устанавливаем префикс перед вычислением хеша (иначе подпись не будет действительной)
        canonicalizationMethodObject.LoadInput(document);
        canonicalizationMethodObject.GetDigestedOutput(hash);
    }

    private static void SetPrefix(string prefix, XmlNode node)
    {
        foreach (XmlNode n in node.ChildNodes)
            SetPrefix(prefix, n);
        node.Prefix = prefix;
    }
}

`

ComputeSignature Exception

I'm getting an exception while trying to sign some data
"Индекс за пределами диапазона. Индекс должен быть положительным числом, а его размер не должен превышать размер коллекции.
Имя параметра: index"
в System.Security.Cryptography.X509Certificates.X509ChainElementCollection.get_Item(Int32 index)
в System.Security.Cryptography.Pkcs.PkcsUtils.CreateBagOfCertificates(CmsSigner signer)
в System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer, Boolean silent)
в System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner signer, Boolean silent)
в GostCryptography.Pkcs.GostSignedCms.ComputeSignature(CmsSigner signer, Boolean silent)
в GostCryptography.Pkcs.GostSignedCms.ComputeSignature(CmsSigner signer)

Same code works on test machine, but fails on production, same certificate

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

Здравствуйте, при использовании вашей библиотеки в проекте, где используется 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

Не проверяется подпись от ПФР (но проверяется онлайн на КриптоПро DSS)

Времени суток!

Столкнулся со странной бедой: приходят подписанные файлы, которые не хотят проверяться. При том, что с виду там проблем никаких быть не должно.
И всё бы ничего, но их отлично проверяет сервис от КриптоПро! Вот этот: https://www.justsign.me/verifycpca/Verify/
Подпись, сделанную GostCryptography, он, напротив, проверять не хочет.

Я в мат. части тут не очень силён, поэтому могу упускать что-то очень очевидное. Для проверки брал метод VerifyXmlDocumentSignature из тестов.
Заранее благодарен за помощь!

Подпись и проверка подписи XML-документа с предварительным XSLT-преобразованием подписываемых данных

SignedXmlTransformTest - не проходит.

В лог пишет:
System.Security.Cryptography.Xml.SignedXml Information: 17 : [GostSignedXmlImpl#02093e65, UnsafeTransformMethod] Метод преобразования "http://www.w3.org/TR/1999/REC-xslt-19991116" не находится в списке безопасных. Безопасные методы преобразования: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments", "http://www.w3.org/2001/10/xml-exc-c14n#", "http://www.w3.org/2001/10/xml-exc-c14n#WithComments", "http://www.w3.org/2000/09/xmldsig#enveloped-signature", "http://www.w3.org/2000/09/xmldsig#base64", "urn:mpeg:mpeg21:2003:01-REL-R-NS:licenseTransform", "http://www.w3.org/2002/07/decrypt#XML".
System.Security.Cryptography.Xml.SignedXml Information: 12 : [GostSignedXmlImpl#02093e65, VerificationFailure] Проверка Ссылки не прошла.

Одно из решений - добавить в реестр
http://go.microsoft.com/fwlink/?linkid=747061&clcid=0x409

https://support.microsoft.com/en-us/help/3148821/after-you-apply-security-update-3141780-net-framework-applications-enc

Ошибка установки пароля для контейнера

Добрый день. При попытке задать пароль для контейнера закрытого ключа получаю исключение:

Методу "GostCryptography.Gost_R3410.Gost_R3410_AsymmetricAlgorithm`2<TKeyParams,TKeyAlgorithm>.SetSignatureKeyPassword(GostCryptography.Native.SafeProvHandleImpl,

System.Security.SecureString, Int32)", прозрачному для безопасности, не удалось получить доступ к критически важному типу безопасности "GostCryptography.Native.SafeProvHandleImpl".

Сборка "GostCryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" помечена атрибутом AllowPartiallyTrustedCallersAttribute и использует модель прозрачности безопасности уровня 2. Прозрачность уровня 2 делает все методы в сборках AllowPartiallyTrustedCallers прозрачными для безопасности по умолчанию, что может являться причиной этого исключения.

Пример кода:

var pars = x509Certificate.GetPrivateKeyInfo();
		    var gostR3410alg = new Gost_R3410_2001_AsymmetricAlgorithm(pars);
		    gostR3410alg.SetContainerPassword(s); // s - SecureString
			return gostR3410alg; // Ошибка

Может быть я делаю что-то не так и есть какой-то другой способ? В прошлой версии это работало. Аналогичная ошибка и для Gost_R3410_2012_256_AsymmetricAlgorithm и Gost_R3410_2012_512_AsymmetricAlgorithm

Верификация подписи ГОСТ Р 34.10-2012, 256 бит.

Делаю верификацию ЭП — отсоединенную, в формате PKCS#7 по значению хэш-функции

Есть сигнатура отсоединенной подписи и сообщение которую хочу проверить.
При проверке на сайте госуслуг проверка проходит успешно.

Код взял из примера

byte[] signature_byte = System.Convert.FromBase64String("MIIcrwYJKoZIhvcNAQc....");
byte[] message = Encoding.UTF8.GetBytes("Hello world");

var signedCms = new GostSignedCms(new ContentInfo(message), true);
signedCms.Decode(signature_byte);

try
{
// Проверка подписи CMS/PKCS#7
signedCms.CheckSignature(true);
}
catch (Exception exc)
{
}

При выполнении кода вылетает ошибка с текстом: {"Unknown algorithm '1.2.643.7.1.1.1.1'."}
Тестил на компьютерах: С установленной VipNet CSP (4.2.11.58753) и КриптоПро CSP (4.0.9944), так же откомпилированную версию на компьютере только с КриптоПро CSP версии 4.0.9963 (Установлен КриптоПро.NET Сервер версия 1.0.7775.0, КриптоПро.NET SDK версия 1.0.7775.0)
Выходит аналогичная ошибка.

Подскажите в чем может быть проблема?

VipNet 4.4.2 создает провайдеры с типом 75, 80 и 81

В новую версию VipNet 4.4.2 добавили "Совместимость с продуктами КриптоПро"

изображение

Эта штука ставится юзеру по умолчанию. Что происходит в реестре:

изображение

Соответственно, проверки что за криптопровайдер по его типу (75, 80, 81) перестанут работать, т.к. VipNet мимикрирует под CryptoPro, например https://github.com/AlexMAS/GostCryptography/blob/master/Source/GostCryptography/Base/ProviderType.cs - становится немного не актуален, если нужно действительно отделять випнет от криптопро

В официальной документации толком информации про это нет, есть только один абзац, что это сделано якобы для совместимости с плагином криптопро для браузера

Шифрование файла по ГОСТ

Александр, добрый день.
Пытаюсь использовать вашу библиотеку в следующей задаче:
PDF файл зашифровать через CryptoPro и сохранить полученный результат в БД.

Если использую код из примера:

var sharedKey = new Gost28147SymmetricAlgorithm();
var dataStream = new MemoryStream(Encoding.UTF8.GetBytes("Some data for encrypt..."));;

var encryptedDataStream = EncryptDataStream(sharedKey, dataStream);
var decryptedDataStream = DecryptDataStream(sharedKey, encryptedDataStream);

то dataStream совпадает с decryptedDataStream;

но если в dataStream кладу содержимое файла PDF,

dataStream = new MemoryStream(Convert.FromBase64String(obj.Content));

то дешифрованный результат не совпадает с исходным.

win2008r2 + cryptopro5 + gost r2012-256

возможно причина в платформе, но именно такая конфигурация довольно часто имеется у клиентов: winserver2008r2 + crypto-pro5.0.11319.
сертификат с гост2012-256.
при указании сертификата для подписания получаю ошибку:

Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at GostCryptography.Gost_R3410.Gost_R3410_AsymmetricAlgorithm`2..ctor(CspParameters providerParameters, Int32 keySize)
at System.Security.Cryptography.X509Certificates.X509CertificateHelper.GetPrivateKeyAlgorithm(X509Certificate2 certificate)
at GostCryptography.Xml.GostSignedXml.SetSigningCertificate(X509Certificate2 certificate)

Создание подписи через КриптоПро, проверка через VipNet

Добрый день!
Попробовал воспользоваться Вашей библиотекой для подписи и проверки подписи потока байт с помощью сертификата и классов форматирования для ГОСТов 2012 года. Использовал код из примеров. При тестировании сложилась следующая картина:

  • Подпись на машине с КриптоПро Csp -> проверка на машине с КриптоПро Csp (работает)
  • Подпись на машине с VipNet Csp -> проверка на машине с VipNet Csp (работает)
  • Подпись на машине с VipNet Csp -> проверка на машине с КриптоПроCsp (работает)
  • Подпись на машине с КриптоПро Csp -> проверка на машине с VipNet Csp (ошибка: Указан неправильный алгоритм)

Оба варианта csp последних версий. Это ошибка библиотеки или недоработки в VipNet Csp? По ГОСТам 2001 года все 4 теста отрабатывают без ошибок.

Поддержка WCF

Здравствуйте, имеется WCF-сервис, разработанный сторонней компанией, и клиент. Для работы клиента требуется CryptoPro .NET, возможно ли использование вашей библиотеки вместо платного CryptoPro .NET?

А подписывать можно только HASH данных?

Здравствуйте.
Есть ли возможность подписывать сообщение, а не HASH, чтобы сделать один файл с прикрепленной подписью?
Например для просмотра через КриптоАрм.
http://cpdn.cryptopro.ru/content/cades/plugin-samples-sign-detached.html

Вот что я имею в виду:
JavaScript

var oSignedData = cadesplugin.CreateObject("CAdESCOM.CadesSignedData");
oSignedData.Content = dataToSign; // тут передаются данные.
var sSignedMessage = oSignedData.SignCades(oSigner, CADESCOM_CADES_BES, detached=false); //это сообщение с прикрепленной подписью.

P.S.
На всякий случай, для проверки попробовал подписать данные в GostCryptography, и получил ошибку System.ArgumentOutOfRangeException: "Hash size must be 64 bytes.
Подумал а вдруг получится, но нет :)

private static byte[] CreateSignature1(GostAsymmetricAlgorithm privateKey, byte[] msgBytes)
{
  return privateKey.CreateSignature(msgBytes);
}

Спасибо!

ЭЛН 2.0

Здравствуйте, коллеги!
С 2017 года используем GostCryptography для взаимодействия с ФСС в части обмена данными ЭЛН. За библиотеку Автору отдельное спасибо. Все прекрасно работало, до появления сервиса версии 2.0.

С появлением нового сервиса, на запрос ЭЛН по № и СНИЛС (в тестовый контур https://docs-test.fss.ru/ws-insurer-crypto-v20/FileOperationsLnService), всегда возвращается ошибка: "ru.fss.integration.ws.fault.v01.InternalException: Не удалось расшифровать сообщение. Возможно сообщение зашифровано на ключе отличном от ключа уполномоченного лица ФСС. Проверьте правильность и актуальность ключа уполномоченного лица ФСС. class ru.ibs.cryptopro.jcp.eln.crypt.CryptoException".

В процессе отладки удалось выяснить, что тестовый контур ЭЛН 2.0 не принимает сертификат уполномоченного лица ФСС для тестового контура (https://cabinets-test.fss.ru/FSS_TEST_CERT_2021.cer), а только сертификат для рабочего контура (https://cabinets.fss.ru/FSS_PROD_CERT_2021.cer). Также тестовый контур 2.0 (в отличии от тестового контура 1.1) не принимает тестовые сертификаты (выданные тестовыми УЦ), а только выданные акредитованными УЦ (т.е. полноценные сертификаты).

При выполнении этих условий АРМ ФСС выполняет запрос ЭЛН по № и СНИЛС и ему сервис возвращает: "Ошибка: ORA-20001: Некорректные параметры: Рег. номер в запросе и ОГРН в сертификате ЭП. Не найден страхователь с такими параметрами, а также отсутствует уполномоченный представитель с таким сертификатом ЭП". Что, в общем корректно (если не обращать внимание, что контур тестовый), так как используется сертификат страхователя, который не участвует в обмене данными ЭЛН.

Запрос в тестовый контур ЭЛН 2.0 без шифрования данных (https://docs-test.fss.ru/ws-insurer-v20/FileOperationsLnService) выполняется и сервис возвращает: "ORA-20001: Номер 306735316028 принадлежит к ЛН на бумажном бланке". Что тоже выглядит корректно. То есть, на лицо проблема с шифрованием (или расшифровыванием на стороне ФСС) сообщения.

Код метода и текст сообщения, передаваемое сервису ФСС в следующих сообщениях.

Кто ни будь подскажите, в чем моя ошибка.

Support for GOST_R_34.10-2012

Current version lacks support for GOST 34.10-2012 (aka Streebog) signatures.

About signature algoritm

  • OID: 1.2.643.2.2.3
  • xmldsig:
    "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256"
    "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-512"

About hash algoritms

There are VipNet and CryptoPro implementations. But I have tested only VipNet. Rumors say that they are not compatible with each other. For me VipNet implementation is most important by now.

UPD: update algoritm info

(кстати, отвечать можно и на русском, если так удобнее)

Выбор предпочитаемого криптопровайдера для алгоритма

Ситуация следующая: на одном сервере установлены КриптоПРО 4 и VipNet. При шифровании по ГОСТ 34.10 - 2012 (ЭЛН и ФСС :)) выдавалось сообщение "Плохой ключ" при попытке шифрования сессионного ключа.

Даже при использовании в коде

 using (var sessionKey = new Gost_28147_89_SymmetricAlgorithm(ProviderType.CryptoPro_2012_512))

Сама ошибка:

System.Security.Cryptography.CryptographicException: Плохой ключ.

   в GostCryptography.Native.CryptoApiHelper.ExportCspBlob(SafeKeyHandleImpl symKeyHandle, SafeKeyHandleImpl keyExchangeHandle, Int32 blobType)
   в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeAlgorithm.EncodeKeyExchangeInternal(Gost_28147_89_SymmetricAlgorithm keyExchangeAlgorithm, Int32 keyExchangeExportAlgId)
   в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeAlgorithm.EncodeKeyExchangeInternal(Gost_28147_89_SymmetricAlgorithm keyExchangeAlgorithm, GostKeyExchangeExportMethod keyExchangeExportMethod)
   в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeAlgorithm.EncodeKeyExchange(SymmetricAlgorithm keyExchangeAlgorithm, GostKeyExchangeExportMethod keyExchangeExportMethod)
   в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeFormatter`3.CreateKeyExchangeInfo(SymmetricAlgorithm keyExchangeAlgorithm)
   в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeFormatter`3.CreateKeyExchangeData(SymmetricAlgorithm keyExchangeAlgorithm)
   в GostCryptography.Xml.GostEncryptedXmlImpl.EncryptKey(Gost_28147_89_SymmetricAlgorithmBase sessionKey, GostAsymmetricAlgorithm publicKey)
   в GostCryptography.Xml.GostEncryptedXml.EncryptKey(Gost_28147_89_SymmetricAlgorithmBase sessionKey, GostAsymmetricAlgorithm publicKey)

Для себя решил проблему, изменив в Native\CryptoAPIHelper.cs в методе public static ProviderType GetAvailableProviderType_2012_512()
Сначала проверку на установленный криптопро, затем на випнет.

Собственно вопрос: а как можно в новой версии установить предпочитаемый тип криптопровайдера? В классе GostCryptoConfig они все readonly.

Утечки памяти в GostCryptography

Здравствуйте! Возможны ли утечки памяти при использовании библиотеки GostCryptography? Обращался ли к Вам кто-либо с данной проблемой? В коде своих сервисов все объекты после использования мы освобождаем. Мы используем GostCryptography для шифрования и подписи сообщений. Взаимодействие с сервисом ФСС для отправки ЭЛН(шифрование) и взаимодействие с Федеральной электронной регистратурой (подпись запросов). На сервере в продуктивном контуре, где запущены наши сервисы, стоит крипто-про CSP 4.0.9963, Версия ядра СКЗИ: 4.0.9014 KC1. ОС: Windows Server 2016 Standart, наблюдается постоянное увеличение памяти, используемое сервисами. Может подскажите куда копать?

Реализация под Net 5

Хотим переехать на новую платформу, а не можем из-за отсутствия GostCryptography...
Очень прошу рассмотреть возможность портировать библиотеку под Net 5. или .Net Core

Совместная работа КриптоПро и ВипНет

День добрый.

Просто хотелось бы уточнить: проверялась ли работа библиотеки при одновременной установке в системе обоих криптопровайдеров?

При следующем вызове:

using (var gost28147 = new Gost_28147_89_SymmetricAlgorithm(provider.ProviderType)) {
    var encryptedData = new GostEncryptedXml(provider.ProviderType).EncryptData(xmlElement, gost28147, false);
    var encryptedKey = GostEncryptedXml.EncryptKey(
        gost28147,
        (GostAsymmetricAlgorithm)receiverCertificate.GetPublicKeyAlgorithm()
    );
}

У меня возникает вот такая ситуация:

System.Security.Cryptography.CryptographicException : Плохой ключ.
в GostCryptography.Native.CryptoApiHelper.ExportCspBlob(SafeKeyHandleImpl symKeyHandle, SafeKeyHandleImpl keyExchangeHandle, Int32 blobType)
в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeAlgorithm.EncodeKeyExchangeInternal(Gost_28147_89_SymmetricAlgorithm keyExchangeAlgorithm, Int32 keyExchangeExportAlgId)
в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeFormatter3.CreateKeyExchangeInfo(SymmetricAlgorithm keyExchangeAlgorithm) в GostCryptography.Gost_R3410.Gost_R3410_KeyExchangeFormatter3.CreateKeyExchangeData(SymmetricAlgorithm keyExchangeAlgorithm)

Причём речь идёт только про КриптоПро. ВипНет работает без проблем. Если удалить ВипНет из системы, то начинает работать и КриптоПро. 2001 или 2012 ГОСТ значения не имеет.

Взаимодействие с федеральными сервисами. Формирование jwt токена с использованием GOST3410.

День добрый!

Используем Вашу библиотеку, наверное единственное что удалось найти на просторах интернета для подписи с использованием сертификата GOST 3410 в среде Windows. Задача: осуществить взаимодействие с фед. сервисами.
В описании указано:

Требования к формированию токена, подписанного сертификатом ГОСТ Р 34.10-2012
1. Подпись токена (signature) должна быть сформирована в формате pkcs#7. При этом для подписи необходимо оставить только блок SignerInfo и убрать из нее данные сертификата;
2. В заголовке токена (Header) в блок “x5c” не нужно помещать всю цепочку сертификатов так как это влечет за собой превышение лимита длины заголовка запроса.

В итоге получаем при любом раскладе ошибку "GW-059: Неверное значение закодированной формы токена".
Более детальной информации, к сожалению не удается узнать, что не так в формируемом токене.

Окружение:

  • сервис на C# (NetFramework 4.7.2)
  • нугет библиотеки: GostCryptography 2.0.9.
  • Установлен КриптоПРО CSP 4.0.9963

За основу взят пример https://github.com/AlexMAS/GostCryptography/blob/master/Source/GostCryptography.Tests/Pkcs/SignedCmsSignTest.cs

Исходный код (для облегчение и сокращения кода, часть кода убрана, суть остается):

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using GostCryptography.Base;
using GostCryptography.Gost_R3410;

var certStore = new X509Store(StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
var collection = certStore.Certificates;
var searchRes = collection.Find(X509FindType.FindBySerialNumber, serialNumber, false);
var cert = searchRes[0];

var alg = string.Empty;
switch (cert.PublicKey.Oid.Value)
{
case "1.2.643.2.2.19":
alg = "GOST3410-2001";
break;
case "1.2.643.7.1.1.1.1":
alg = "ECGOST3410-2012";
break;
case "1.2.643.7.1.1.1.2":
alg = "ECGOST3410-2012";
break;
}

JwtHeader header = new JwtHeader()
{
{ "alg", alg },
{ "x5c", Convert.ToBase64String(cert.GetRawCertData()) },
};

JwtPayload payload = new JwtPayload()
{
{ "sub", "CD28DB17-8A5E-4DDC-8C0B-0F6C10C9B041" }, /* произвольный гуид */
{ "aud", "http://ya.ru" }, /* произвольный адрес */
{ "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
{ "exp", DateTimeOffset.UtcNow.Add(new TimeSpan(0, 10, 0)).ToUnixTimeSeconds() }
};

JwtSecurityToken token = new JwtSecurityToken(header, payload);
string message = token.EncodedHeader + "." + token.EncodedPayload;

// Создание объекта для подписи сообщения
ContentInfo contentInfo = new ContentInfo(Encoding.UTF8.GetBytes(message));
GostCryptography.Pkcs.GostSignedCms signedCms = new GostCryptography.Pkcs.GostSignedCms(contentInfo);
// Создание объект с информацией о подписчике
CmsSigner cmsSigner = new CmsSigner(cert);
// Включение информации только о конечном сертификате (только для теста)
cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;
// Создание подписи для сообщения CMS/PKCS#7
signedCms.ComputeSignature(cmsSigner);
// Создание сообщения CMS/PKCS#7
byte[] signature = signedCms.Encode();

var encodedSignature = Microsoft.IdentityModel.Tokens.Base64UrlEncoder.Encode(signature);

var jwtToken = $"{message}.{encodedSignature}";

/* в итоге получаем токен из трех составляющих
token.EncodedHeader + "." + token.EncodedPayload + "." + encodedSignature */

И при обращении, при любом раскладе получаем ошибку:
"GW-059: Неверное значение закодированной формы токена".
Что конкретно не так в токене, выяснить не удается.

В описании имеется фраза: "и убрать из нее данные сертификата;" - пробовали делать signedCms.Certificates.Clear(); перед вызовом signedCms.Encode();, не помогает.

Не можем понять что может быть. Может у нас что-то не так недонастроено, или какой-то строки кода не хватает.
Или всё же пытаться выяснять что не так в формате.

Подскажите пожалуйста, что может быть, по какому пути идти ?

Проверка подписи и оригинала файла

Здравствуйте, в общем пытаюсь пользоваться библиотекой для проверки оригинала файла и подписи. Делаю как то так:

public void CheckSignature()
{

        string sgnPath = "D:/test/5d3ef84a-8328-44de-b97a-e5d6ce82e1b9.docx.sgn";
        string docxPath = "D:/test/5d3ef84a-8328-44de-b97a-e5d6ce82e1b9.docx";
        byte[] sgnBuffer = new byte[0];>             
        using (var sgnStream = new FileStream(sgnPath, FileMode.Open))
        {
            sgnBuffer = new byte[(int)sgnStream.Length];
            sgnStream.Read(sgnBuffer, 0, (int)sgnStream.Length);
            GostSignedCms cms = new GostSignedCms();
            cms.Decode(sgnBuffer); 
            var certificate = cms.Certificates[0];
            var publicKey = (GostAsymmetricAlgorithm)certificate.GetPublicKeyAlgorithm();

            using (var docxStream = new FileStream(docxPath, FileMode.Open))
            {
                var res = VerifySignature(publicKey, docxStream, sgnBuffer);
                Console.WriteLine(res);
                Console.Read();
            }
        }
    }
    private static bool VerifySignature(AsymmetricAlgorithm publicKey, Stream dataStream, byte[] signature)
    {
        var signatureDescription = (SignatureDescription)GostCryptoConfig.CreateFromName(publicKey.SignatureAlgorithm);

        byte[] hash;

        using (var hashAlg = signatureDescription.CreateDigest())
        {
            hash = hashAlg.ComputeHash(dataStream);
        }

        var deformatter = signatureDescription.CreateDeformatter(publicKey);
        deformatter.SetHashAlgorithm(signatureDescription.DigestAlgorithm);

        return deformatter.VerifySignature(hash, signature);
    }

По моим доводам вроде как все верно, но deformatter.VerifySignature(hash, signature) дает отрицательный результат. Вот тут https://crypto.kontur.ru/verify проверял файл и подпись все нормально. Подскажите пожалуйста что я делаю не так?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.