Подпись ИЭМК с помощью VipNet CSP: различия между версиями

Материал из Wiki МИАЦ ВО
Перейти к навигации Перейти к поиску
Строка 49: Строка 49:
 
         }
 
         }
 
</pre>
 
</pre>
Далее. Для подписи требуется библиотека GostCryptography. Заливаем через nuget, подключаем.
+
Далее. Для подписи требуется библиотека GostCryptography (https://github.com/AlexMAS/GostCryptography). Заливаем через nuget, подключаем.
 +
 
 
<pre>
 
<pre>
 
using GostCryptography;
 
using GostCryptography;
Строка 150: Строка 151:
 
         }
 
         }
 
</pre>
 
</pre>
 +
 +
Вызов класса
 +
<pre>SignSmevRequestVip(args[0], args[1], CertItog);</pre>

Версия 14:44, 20 октября 2016

Поиск нужного сертификата. Ищем по конкретному СНИЛСу и действующий на текущую дату.

X509Certificate2 CertItog = find_certificate_();
        public static X509Certificate2 find_certificate_()
        {

            X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
            X509Certificate2 cert = new X509Certificate2();
            X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
            X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
            string str_SN = "";
            foreach (X509Certificate2 x509 in fcollection)
            {
                try
                {
                    if (x509.Subject.ToUpper().Contains("SNILS") || x509.Subject.ToUpper().Contains("СНИЛС"))
                    {

                        str_SN = x509.Subject.Substring(x509.Subject.IndexOf("SNILS") + 6, 11);
                        int n;
                        if (!int.TryParse(str_SN.Substring(0, 10), out n))
                        {
                            str_SN = x509.Subject.Substring(x509.Subject.ToUpper().IndexOf("СНИЛС") + 6, 11);
                            if (!int.TryParse(str_SN.Substring(0, 10), out n))
                            {
                                continue;
                                //                                System.Windows.Forms.MessageBox.Show("Снилс в сертификате не найден или пустой");
                            }
                        }
                        if (String.CompareOrdinal(str_SN, "NNNNNNNNNNNNN") == 0)
                        {
                            cert = x509;
                            //                            Console.WriteLine(cert.Subject);
                            Console.WriteLine(str_SN);
//                            Console.ReadKey();
                            break;
                        }
                    }
                    x509.Reset();
                }
                catch (CryptographicException)
                {
                    Console.WriteLine("Information could not be written out for this certificate.");
                }
            }
            store.Close();
            return cert;
        }

Далее. Для подписи требуется библиотека GostCryptography (https://github.com/AlexMAS/GostCryptography). Заливаем через nuget, подключаем.

using GostCryptography;
using GostCryptography.Cryptography;
using GostCryptography.Xml;

Для СМЭВ пользуем доп. класс Добавляем константы

        private const string WsSecurityExtNamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
        private const string WsSecurityUtilityNamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
        private static XmlElement GetSmevIdElement(XmlDocument document, string idValue)
        {
                var namespaceManager = new XmlNamespaceManager(document.NameTable);
                namespaceManager.AddNamespace("wsu", WsSecurityUtilityNamespace);
                return document.SelectSingleNode("//*[@wsu:Id='" + idValue + "']", namespaceManager) as XmlElement;
        }

И, собственно алгоритм подписи/ На выходе формируется отдельный файл.

        private static XmlDocument SignSmevRequestVip(string FileName, string SignedFileName, X509Certificate2 signingCertificate)
        {
            XmlDocument smevRequest = new XmlDocument();
            smevRequest.PreserveWhitespace = true;
            smevRequest.Load(new XmlTextReader(FileName));

            // Создание подписчика XML-документа
            var signedXml = new GostSignedXml(smevRequest) { GetIdElementHandler = GetSmevIdElement };

            // Установка ключа для создания подписи
            signedXml.SetSigningCertificate(signingCertificate);
          
            // Ссылка на узел, который нужно подписать, с указанием алгоритма хэширования ГОСТ Р 34.11-94 (в соответствии с методическими рекомендациями СМЭВ)
            var dataReference = new Reference { Uri = "#BODY", DigestMethod = GostSignedXml.XmlDsigGost3411ObsoleteUrl };
            // Метод преобразования, применяемый к данным перед их подписью (в соответствии с методическими рекомендациями СМЭВ)
            var dataTransform = new XmlDsigExcC14NTransform();
            dataReference.AddTransform(dataTransform);
            // Установка ссылки на узел
            signedXml.AddReference(dataReference);
//reference #wsa300
            var dataReferenceWSA300 = new Reference { Uri = "#WSA-300", DigestMethod = GostSignedXml.XmlDsigGost3411ObsoleteUrl };
            var dataTransformWSA300 = new XmlDsigExcC14NTransform();
            dataReferenceWSA300.AddTransform(dataTransformWSA300);
            signedXml.AddReference(dataReferenceWSA300);
//reference #WSA-301
            var dataReferenceWSA301 = new Reference { Uri = "#WSA-301", DigestMethod = GostSignedXml.XmlDsigGost3411ObsoleteUrl };
            var dataTransformWSA301 = new XmlDsigExcC14NTransform();
            dataReferenceWSA301.AddTransform(dataTransformWSA301);
            signedXml.AddReference(dataReferenceWSA301);
//reference #WSA-302
            var dataReferenceWSA302 = new Reference { Uri = "#WSA-302", DigestMethod = GostSignedXml.XmlDsigGost3411ObsoleteUrl };
            var dataTransformWSA302 = new XmlDsigExcC14NTransform();
            dataReferenceWSA302.AddTransform(dataTransformWSA302);
            signedXml.AddReference(dataReferenceWSA302);
//reference #WSA-303
            var dataReferenceWSA303 = new Reference { Uri = "#WSA-303", DigestMethod = GostSignedXml.XmlDsigGost3411ObsoleteUrl };
            var dataTransformWSA303 = new XmlDsigExcC14NTransform();
            dataReferenceWSA303.AddTransform(dataTransformWSA303);
            signedXml.AddReference(dataReferenceWSA303);
//reference #TRHEAD
            var dataReferenceTRHEAD = new Reference { Uri = "#TRHEAD", DigestMethod = GostSignedXml.XmlDsigGost3411ObsoleteUrl };
            var dataTransformTRHEAD = new XmlDsigExcC14NTransform();
            dataReferenceTRHEAD.AddTransform(dataTransformTRHEAD);
            signedXml.AddReference(dataReferenceTRHEAD);
//reference #CertId
            var dataReferenceCertId = new Reference { Uri = "#CertId", DigestMethod = GostSignedXml.XmlDsigGost3411ObsoleteUrl };
            var dataTransformCertId = new XmlDsigExcC14NTransform();
            dataReferenceCertId.AddTransform(dataTransformCertId);
            signedXml.AddReference(dataReferenceCertId);

            // Установка алгоритма нормализации узла SignedInfo (в соответствии с методическими рекомендациями СМЭВ)
            signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

            // Установка алгоритма подписи ГОСТ Р 34.10-2001 (в соответствии с методическими рекомендациями СМЭВ)
            signedXml.SignedInfo.SignatureMethod = GostSignedXml.XmlDsigGost3410ObsoleteUrl;

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

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

            // Добавление подписи в исходный документ
            smevRequest.GetElementsByTagName("Signature")[0].PrependChild(smevRequest.ImportNode(signatureXml.GetElementsByTagName("SignatureValue")[0], true));
            smevRequest.GetElementsByTagName("Signature")[0].PrependChild(smevRequest.ImportNode(signatureXml.GetElementsByTagName("SignedInfo")[0], true));
            smevRequest.GetElementsByTagName("wsse:BinarySecurityToken")[0].InnerText = Convert.ToBase64String(signingCertificate.RawData);

            using (XmlTextWriter xmltw = new XmlTextWriter(SignedFileName,
                new UTF8Encoding(false)))
            {
                smevRequest.WriteTo(xmltw);
            }
            return smevRequest;
        }

Вызов класса

SignSmevRequestVip(args[0], args[1], CertItog);