Esempio n. 1
0
        public VerifierResponse VerifyXmlSignature(
            SignatureType mode,
            XmlDocument message,
            string certificateFilePath = null,
            string certificateThumb    = null,
            string nodeId = null,
            bool isVerifyCertificateChain = false)
        {
            SignedXml signedXml = new SignedXml(message);

            Signer.Smev2SignedXml smev2SignedXml = null;

            X509Certificate2 cert = null;
            bool             isCerFile;

            if ((isCerFile = !string.IsNullOrEmpty(certificateFilePath)) ||
                !string.IsNullOrEmpty(certificateThumb))
            {
                //means we are testing signature on external certificate
                if (isCerFile)
                {
                    cert = new X509Certificate2();
                    try
                    {
                        cert.Import(certificateFilePath);
                    }
                    catch (Exception e)
                    {
                        throw ExceptionFactory.GetException(
                                  ExceptionType.CertificateImportException,
                                  certificateFilePath,
                                  e.Message);
                    }
                }
                else
                {
                    //throws if not found
                    ICertificateProcessor cp = new CertificateProcessor();
                    cert = cp.SearchCertificateByThumbprint(certificateThumb);
                }
            }

            XmlNodeList signaturesInDoc =
                message.GetElementsByTagName(
                    "Signature",
                    SignedXml.XmlDsigNamespaceUrl
                    );

            var signatures =
                signaturesInDoc
                .Cast <XmlElement>()
                .ToDictionary(
                    (elt) =>
            {
                XNamespace ns = elt.GetXElement().Name.Namespace;
                return(elt.GetXElement().Descendants(ns + "Reference").First().Attributes("URI").First()
                       .Value.Replace("#", ""));
            },
                    (elt => elt)
                    );

            if (!string.IsNullOrEmpty(nodeId) &&
                !signatures.ContainsKey(nodeId))
            {
                throw ExceptionFactory.GetException(ExceptionType.ReferencedSignatureNotFound, nodeId);
            }

            if (signaturesInDoc.Count == 0)
            {
                throw ExceptionFactory.GetException(ExceptionType.NoSignaturesFound);
            }

            switch (mode)
            {
            case SignatureType.Smev2BaseDetached:
                smev2SignedXml = new Signer.Smev2SignedXml(message);
                try
                {
                    smev2SignedXml.LoadXml(
                        !string.IsNullOrEmpty(nodeId)
                                                                ? signatures[nodeId]
                                                                : signatures["body"]);
                }
                catch (Exception e)
                {
                    throw ExceptionFactory.GetException(ExceptionType.CertificateContentCorrupted, e.Message);
                }

                XmlNodeList referenceList =
                    smev2SignedXml.KeyInfo
                    .GetXml()
                    .GetElementsByTagName("Reference", Signer.WsSecurityWsseNamespaceUrl);
                if (referenceList.Count == 0)
                {
                    throw ExceptionFactory.GetException(ExceptionType.Smev2CertificateReferenceNotFound);
                }

                string binaryTokenReference = ((XmlElement)referenceList[0]).GetAttribute("URI");
                if (string.IsNullOrEmpty(binaryTokenReference) ||
                    binaryTokenReference[0] != '#')
                {
                    throw ExceptionFactory.GetException(ExceptionType.Smev2MalformedCertificateReference);
                }

                XmlElement binaryTokenElement = smev2SignedXml.GetIdElement(
                    message,
                    binaryTokenReference.Substring(1));
                if (binaryTokenElement == null)
                {
                    throw ExceptionFactory.GetException(
                              ExceptionType.Smev2CertificateNotFound,
                              binaryTokenReference.Substring(1));
                }

                try
                {
                    cert = new X509Certificate2(Convert.FromBase64String(binaryTokenElement.InnerText));
                }
                catch (Exception e)
                {
                    throw ExceptionFactory.GetException(ExceptionType.Smev2CertificateCorrupted, e.Message);
                }

                break;

            case SignatureType.Smev2ChargeEnveloped:
                if (signaturesInDoc.Count > 1)
                {
                    throw ExceptionFactory.GetException(
                              ExceptionType.ChargeTooManySignaturesFound,
                              signaturesInDoc.Count);
                }

                if (!ChargeStructureOk(message))
                {
                    throw ExceptionFactory.GetException(ExceptionType.ChargeMalformedDocument);
                }

                try
                {
                    signedXml.LoadXml(signatures.First().Value);
                }
                catch (Exception e)
                {
                    throw ExceptionFactory.GetException(ExceptionType.CertificateContentCorrupted, e.Message);
                }

                break;

            case SignatureType.Smev2SidebysideDetached:
            case SignatureType.Smev3BaseDetached:
            case SignatureType.Smev3SidebysideDetached:
                try
                {
                    XmlDsigSmevTransform smevTransform = new XmlDsigSmevTransform();
                    signedXml.SafeCanonicalizationMethods.Add(smevTransform.Algorithm);

                    signedXml.LoadXml(
                        !string.IsNullOrEmpty(nodeId)
                                                                ? signatures[nodeId]
                                                                : signatures.First().Value);
                }
                catch (Exception e)
                {
                    throw ExceptionFactory.GetException(ExceptionType.CertificateContentCorrupted, e.Message);
                }

                break;

            case SignatureType.Pkcs7String:
            case SignatureType.Pkcs7StringAllCert:
            case SignatureType.Pkcs7StringNoCert:
            case SignatureType.SigDetached:
            case SignatureType.SigDetachedAllCert:
            case SignatureType.SigDetachedNoCert:
                throw new NotSupportedException(
                          $"Detached signature verification is not supported by this method. Use {nameof(VerifyDetachedSignature)} method instead.");

            case SignatureType.Unknown:
            case SignatureType.Smev3Ack:
            case SignatureType.Rsa2048Sha256String:
            case SignatureType.RsaSha256String:
                throw ExceptionFactory.GetException(ExceptionType.UnsupportedSignatureType, mode);

            default:
                throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
            }

            var isSignatureValid = smev2SignedXml?.CheckSignature(cert.PublicKey.Key)
                                   ??
                                   (cert == null
                                        ? signedXml.CheckSignature()
                                        : signedXml.CheckSignature(cert, true)
                                   );

            var isCertificateChainValid = cert?.Verify() ?? true;

            StringBuilder verificationMessage = new StringBuilder();

            if (!isSignatureValid)
            {
                verificationMessage.AppendLine("Signature is invalid");
            }

            if (!isCertificateChainValid)
            {
                verificationMessage.AppendLine("Certificate chain is invalid");
            }

            var verifierResponse = new VerifierResponse()
            {
                IsCertificateChainValid        = isCertificateChainValid,
                IsSignatureMathematicallyValid = isSignatureValid,
                IsSignatureSigningDateValid    = true,              // we do not check this for this type of signature
                Message = verificationMessage.ToString()
            };

            return(verifierResponse);
        }
Esempio n. 2
0
        public static XmlDocument SignXmlFileSmev3(XmlDocument doc, X509Certificate2 certificate, string signingNodeId, bool assignDs, bool isAck = false, bool isSidebyside = false)
        {
            XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);

            nsm.AddNamespace("ns", "urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1");
            nsm.AddNamespace("ns1", "urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1");
            nsm.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");


            SignedXml sxml = new SignedXml(doc)
            {
                SigningKey = certificate.PrivateKey
            };

            //=====================================================================================REFERENCE TRASFORMS
            Reference reference = new Reference {
                Uri = "#" + signingNodeId,
#pragma warning disable 612
                //Расчет хеш-суммы ГОСТ Р 34.11-94 http://www.w3.org/2001/04/xmldsig-more#gostr3411
                DigestMethod = CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3411UrlObsolete
#pragma warning disable 612
            };

            XmlDsigExcC14NTransform excC14n = new XmlDsigExcC14NTransform();

            reference.AddTransform(excC14n);

            XmlDsigSmevTransform smevTransform = new XmlDsigSmevTransform();

            reference.AddTransform(smevTransform);

            if (isAck)
            {
                XmlDsigEnvelopedSignatureTransform enveloped = new XmlDsigEnvelopedSignatureTransform();
                reference.AddTransform(enveloped);
            }

            sxml.AddReference(reference);

            //=========================================================================================CREATE SIGNATURE
            sxml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

            //Формирование подписи ГОСТ Р 34.10-2001 http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411
            sxml.SignedInfo.SignatureMethod = CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3410UrlObsolete;
            KeyInfo         keyInfo     = new KeyInfo();
            KeyInfoX509Data X509KeyInfo = new KeyInfoX509Data(certificate);

            keyInfo.AddClause(X509KeyInfo);
            sxml.KeyInfo = keyInfo;

            sxml.ComputeSignature();

            XmlElement signature = sxml.GetXml();

            //==================================================================================================add ds:
            if (assignDs)
            {
                _assignNsPrefix(signature, "ds");
                XmlElement xmlSignedInfo = signature.SelectSingleNode("ds:SignedInfo", nsm) as XmlElement;

                XmlDocument document = new XmlDocument();
                document.PreserveWhitespace = false;
                document.LoadXml(xmlSignedInfo.OuterXml);

                //create new canonicalization object based on original one
                Transform canonicalizationMethodObject = sxml.SignedInfo.CanonicalizationMethodObject;
                canonicalizationMethodObject.LoadInput(document);

                //get new hshing object based on original one
                SignatureDescription description =
                    CryptoConfig.CreateFromName(sxml.SignedInfo.SignatureMethod) as SignatureDescription;
                if (description == null)
                {
                    throw new CryptographicException(
                              $"Не удалось создать объект SignatureDescription по имени [{sxml.SignedInfo.SignatureMethod}]");
                }
                HashAlgorithm hash = description.CreateDigest();
                if (hash == null)
                {
                    throw new CryptographicException(
                              $"Не удалось создать объект HashAlgorithm из SignatureDescription по имени [{sxml.SignedInfo.SignatureMethod}]");
                }

                //compute new SignedInfo digest value
                byte[] hashVal = canonicalizationMethodObject.GetDigestedOutput(hash);

                //compute new signature
                XmlElement xmlSignatureValue = signature.SelectSingleNode("ds:SignatureValue", nsm) as XmlElement;
                xmlSignatureValue.InnerText =
                    Convert.ToBase64String(description.CreateFormatter(sxml.SigningKey).CreateSignature(hashVal));
            }
            //=============================================================================APPEND SIGNATURE TO DOCUMENT
            if (!isSidebyside)
            {
                doc.GetElementsByTagName("CallerInformationSystemSignature",
                                         "urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1")[0].InnerXml = "";
                doc.GetElementsByTagName("CallerInformationSystemSignature",
                                         "urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1")[0].AppendChild(signature);
            }
            else
            {
                getNodeWithAttributeValue(doc.ChildNodes, signingNodeId)?.ParentNode?.AppendChild(signature);
            }
            return(doc);
        }
        public static bool Signed(string file, string sigFile, X509Certificate2 certificate, bool MessageID = true)
        {
            //-------------------------------------------
            // Создаем новый документ XML.
            XmlDocument doc = new XmlDocument
            {
                PreserveWhitespace = true
            };
            // Читаем документ из файла.
            XmlTextReader XmlTxtRead = new XmlTextReader(file);

            doc.Load(XmlTxtRead);
            XmlTxtRead.Close();

            // Создаём объект SmevSignedXml - наследник класса SignedXml с перегруженным GetIdElement
            // для корректной обработки атрибута wsu:Id.
            _SignedXml _signedXml = new _SignedXml(doc)
            {
                // Задаём ключ подписи для документа SmevSignedXml.
                SigningKey = certificate.PrivateKey
            };
            //-------------------------------------------

            string IdMessageTypeSelector = "";

            if (doc.GetElementsByTagName("MessageTypeSelector", "*")[0] != null)
            {
                IdMessageTypeSelector = doc.GetElementsByTagName("MessageTypeSelector", "*")[0].Attributes["Id"].Value;
            }

            if (doc.GetElementsByTagName("AckTargetMessage", "*")[0] != null)
            {
                IdMessageTypeSelector = doc.GetElementsByTagName("AckTargetMessage", "*")[0].Attributes["Id"].Value;
            }

            if (doc.GetElementsByTagName("SenderProvidedResponseData", "*")[0] != null)
            {
                IdMessageTypeSelector = doc.GetElementsByTagName("SenderProvidedResponseData", "*")[0].Attributes["Id"].Value;
            }

            if (doc.GetElementsByTagName("Timestamp", "*")[0] != null)
            {
                if (doc.GetElementsByTagName("Timestamp", "*")[0].Attributes["Id"] != null)
                {
                    IdMessageTypeSelector = doc.GetElementsByTagName("Timestamp", "*")[0].Attributes["Id"].Value;
                }
            }

            if (doc.GetElementsByTagName("SenderProvidedRequestData", "*")[0] != null)
            {
                IdMessageTypeSelector = doc.GetElementsByTagName("SenderProvidedRequestData", "*")[0].Attributes["Id"].Value;
            }

            // Создаем ссылку на подписываемый узел XML. В данном примере и в методических
            // рекомендациях СМЭВ подписываемый узел soapenv:Body помечен идентификатором "body".
            Reference reference = new Reference
            {
                Uri = "#" + IdMessageTypeSelector
            };

            // Задаём алгоритм хэширования подписываемого узла - ГОСТ Р 34.11-94. Необходимо
            // использовать устаревший идентификатор данного алгоритма, т.к. именно такой
            // идентификатор используется в СМЭВ.
            if (certificate.GetKeyAlgorithm() != "1.2.643.7.1.1.1.1")
            {
                reference.DigestMethod = CPSignedXml.XmlDsigGost3411Url;//ГОСТ Р 34.11-94
            }
            else
            {
                reference.DigestMethod = CPSignedXml.XmlDsigGost3411_2012_256Url;//ГОСТ Р 34.11-2012 256бит
            }

            // Добавляем преобразование для приведения подписываемого узла к каноническому виду
            // по алгоритму http://www.w3.org/2001/10/xml-exc-c14n# в соответствии с методическими
            // рекомендациями СМЭВ.
            XmlDsigExcC14NTransform c14 = new XmlDsigExcC14NTransform();

            reference.AddTransform(c14);
            _signedXml.AddReference(reference);

            // Добавляем преобразование для приведения подписываемого узла к каноническому виду
            // по алгоритму urn://smev-gov-ru/xmldsig/transform в соответствии с методическими
            // рекомендациями СМЭВ.
            XmlDsigSmevTransform dsig = new XmlDsigSmevTransform();

            reference.AddTransform(dsig);
            _signedXml.AddReference(reference);

            // Задаём преобразование для приведения узла ds:SignedInfo к каноническому виду
            // по алгоритму http://www.w3.org/2001/10/xml-exc-c14n# в соответствии с методическими
            // рекомендациями СМЭВ.
            _signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

            // Задаём алгоритм подписи - ГОСТ Р 34.10-2001. Необходимо использовать устаревший
            // идентификатор данного алгоритма, т.к. именно такой идентификатор используется в
            // СМЭВ.
            if (certificate.GetKeyAlgorithm() != "1.2.643.7.1.1.1.1")
            {
                _signedXml.SignedInfo.SignatureMethod = CPSignedXml.XmlDsigGost3410Url;//ГОСТ Р 34.10-2001
            }
            else
            {
                _signedXml.SignedInfo.SignatureMethod = CPSignedXml.XmlDsigGost3410_2012_256Url;//ГОСТ Р 34.10-2012 256бит
            }

            // Create a new KeyInfo object.
            KeyInfo keyInfo = new KeyInfo();

            // Load the certificate into a KeyInfoX509Data object
            // and add it to the KeyInfo object.
            keyInfo.AddClause(new KeyInfoX509Data(certificate));

            // Add the KeyInfo object to the SignedXml object.
            _signedXml.KeyInfo = keyInfo;

            if (doc.GetElementsByTagName("Timestamp", "*")[0] != null)
            {
                //Добавляем время
                doc.GetElementsByTagName("Timestamp", "*")[0].InnerText = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffzzzzz");
            }

            if (MessageID)
            {
                if (doc.GetElementsByTagName("MessageID", "*")[0] != null)
                {
                    //Добавляем UUID
                    doc.GetElementsByTagName("MessageID", "*")[0].InnerText = GuidGenerator.GenerateTimeBasedGuid().ToString();
                }
            }

            // Вычисляем подпись.
            _signedXml.ComputeSignature("ds");
            // Получаем представление подписи в виде XML.
            XmlElement xmlDigitalSignature = _signedXml.GetXml("ds");

            doc.GetElementsByTagName("CallerInformationSystemSignature", "*")[0].PrependChild(
                doc.ImportNode(xmlDigitalSignature, true)
                );

            XmlTextWriter xmltw = new XmlTextWriter(sigFile, new UTF8Encoding(false));

            doc.WriteTo(xmltw);
            xmltw.Close();

            return(true);
        }
Esempio n. 4
0
        /// <summary>
        /// Подпись xml файла
        /// </summary>
        static void SignXmlFile(string FileName,
                                string SignedFileName, AsymmetricAlgorithm Key,
                                X509Certificate Certificate)
        {
            // Создаем новый XML документ.
            XmlDocument doc = new XmlDocument();

            // Пробельные символы участвуют в вычислении подписи и должны быть сохранены для совместимости с другими реализациями.
            doc.PreserveWhitespace = true;

            // Читаем документ из файла.
            doc.Load(new XmlTextReader(FileName));

            // Создаем объект SignedXml по XML документу.
            SignedXml signedXml = new SignedXml(doc);

            // Добавляем ключ в SignedXml документ.
            signedXml.SigningKey = Key;

            // Создаем ссылку на node для подписи.
            // При подписи всего документа проставляем "".
            Reference reference = new Reference();

            reference.Uri = "";

            // Явно проставляем алгоритм хэширования,
            // по умолчанию SHA1.
            reference.DigestMethod =
                SignedXml.XmlDsigGost3411_2012_256Url;

            // Добавляем transform на подписываемые данные
            // для удаления вложенной подписи.
            XmlDsigEnvelopedSignatureTransform env =
                new XmlDsigEnvelopedSignatureTransform();

            reference.AddTransform(env);

            // Добавляем СМЭВ трансформ.
            // начиная с .NET 4.5.1 для проверки подписи, необходимо добавить этот трансформ в довернные:
            // signedXml.SafeCanonicalizationMethods.Add("urn://smev-gov-ru/xmldsig/transform");
            XmlDsigSmevTransform smev =
                new XmlDsigSmevTransform();

            reference.AddTransform(smev);

            // Добавляем transform для канонизации.
            XmlDsigC14NTransform c14 = new XmlDsigC14NTransform();

            reference.AddTransform(c14);

            // Добавляем ссылку на подписываемые данные
            signedXml.AddReference(reference);

            // Создаем объект KeyInfo.
            KeyInfo keyInfo = new KeyInfo();

            // Добавляем сертификат в KeyInfo
            keyInfo.AddClause(new KeyInfoX509Data(Certificate));

            // Добавляем KeyInfo в SignedXml.
            signedXml.KeyInfo = keyInfo;

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

            // Получаем XML представление подписи и сохраняем его
            // в отдельном node.
            XmlElement xmlDigitalSignature = signedXml.GetXml();

            // Добавляем node подписи в XML документ.
            doc.DocumentElement.AppendChild(doc.ImportNode(
                                                xmlDigitalSignature, true));

            // При наличии стартовой XML декларации ее удаляем
            // (во избежание повторного сохранения)
            if (doc.FirstChild is XmlDeclaration)
            {
                doc.RemoveChild(doc.FirstChild);
            }

            // Сохраняем подписанный документ в файле.
            using (XmlTextWriter xmltw = new XmlTextWriter(SignedFileName,
                                                           new UTF8Encoding(false)))
            {
                xmltw.WriteStartDocument();
                doc.WriteTo(xmltw);
            }
        }
Esempio n. 5
0
        static XmlDocument SignXmlFile(XmlDocument doc, AsymmetricAlgorithm Key, X509Certificate Certificate)
        {
            // Создаем объект SignedXml по XML документу.
            SignedXml signedXml = new SignedXml(doc);

            // Добавляем ключ в SignedXml документ.
            signedXml.SigningKey = Key;

            // Создаем ссылку на node для подписи.
            // При подписи всего документа проставляем "".
            Reference reference = new Reference();

            reference.Uri = "";

            // Явно проставляем алгоритм хэширования,
            // по умолчанию SHA1.
            reference.DigestMethod =
                SignedXml.XmlDsigGost3411_2012_256Url;

            // Добавляем transform на подписываемые данные
            // для удаления вложенной подписи.
            XmlDsigEnvelopedSignatureTransform env =
                new XmlDsigEnvelopedSignatureTransform();

            reference.AddTransform(env);

            // Добавляем СМЭВ трансформ.
            // начиная с .NET 4.5.1 для проверки подписи, необходимо добавить этот трансформ в довернные:
            // signedXml.SafeCanonicalizationMethods.Add("urn://smev-gov-ru/xmldsig/transform");
            XmlDsigSmevTransform smev =
                new XmlDsigSmevTransform();

            reference.AddTransform(smev);

            // Добавляем transform для канонизации.
            XmlDsigC14NTransform c14 = new XmlDsigC14NTransform();

            reference.AddTransform(c14);

            // Добавляем ссылку на подписываемые данные
            signedXml.AddReference(reference);

            // Создаем объект KeyInfo.
            KeyInfo keyInfo = new KeyInfo();

            // Добавляем сертификат в KeyInfo
            keyInfo.AddClause(new KeyInfoX509Data(Certificate));

            // Добавляем KeyInfo в SignedXml.
            signedXml.KeyInfo = keyInfo;

            // Можно явно проставить алгоритм подписи: ГОСТ Р 34.10.
            // Если сертификат ключа подписи ГОСТ Р 34.10
            // и алгоритм ключа подписи не задан, то будет использован
            // XmlDsigGost3410Url
            // signedXml.SignedInfo.SignatureMethod =
            //     CPSignedXml.XmlDsigGost3410_2012_256Url;

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

            // Получаем XML представление подписи и сохраняем его
            // в отдельном node.
            XmlElement xmlDigitalSignature = signedXml.GetXml();

            // Добавляем node подписи в XML документ.
            doc.DocumentElement.AppendChild(doc.ImportNode(
                                                xmlDigitalSignature, true));

            // При наличии стартовой XML декларации ее удаляем
            // (во избежание повторного сохранения)
            if (doc.FirstChild is XmlDeclaration)
            {
                doc.RemoveChild(doc.FirstChild);
            }

            return(doc);
        }