コード例 #1
0
        public VerifierResponse CheckSignatureDs(XmlDocument xmlDoc, RSACryptoServiceProvider key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            SignedXml signedXml = new SignedXml(xmlDoc);

            //For XPath
            XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlDoc.NameTable);

            namespaceManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
            //this prefix is arbitrary and used only for XPath

            XmlElement xmlSignature = xmlDoc.SelectSingleNode("//ds:Signature", namespaceManager) as XmlElement;

            signedXml.LoadXml(xmlSignature);

            //These are the three methods called in SignedXml's CheckSignature method, but the built-in CheckSignedInfo will not validate prefixed Signature elements

            var isSignatureValid = _checkSignatureFormat(signedXml) && _checkDigestedReferences(signedXml) &&
                                   CheckSignedInfo(signedXml, key);

            return(isSignatureValid
                                ? VerifierResponse.Valid
                                : VerifierResponse.Invalid("Signature is invalid"));
        }
コード例 #2
0
        private VerifierResponse VerifyDetachedSignature(
            byte[] signedFileBytes,
            byte[] signatureFileBytes,
            bool isVerifyCertificateChain = false)
        {
            ContentInfo contentInfo = new ContentInfo(signedFileBytes);
            SignedCms   signedCms   = new SignedCms(contentInfo, true);

            signedCms.Decode(signatureFileBytes);

            if (signedCms.SignerInfos.Count == 0)
            {
                return(VerifierResponse.Invalid("No signatures found in singature file"));
            }

            if (signedCms.SignerInfos.Count > 1)
            {
                return(VerifierResponse.Invalid($"{signedCms.SignerInfos.Count} signatures found in singature file. Only single-signature files are supported at the moment."));
            }

            SignerInfo signerInfo = signedCms.SignerInfos[0];

            var signingDateTime =
                (signerInfo.SignedAttributes
                 .Cast <CryptographicAttributeObject>()
                 .FirstOrDefault(x => x.Oid.Value == "1.2.840.113549.1.9.5")?.Values[0]
                 as Pkcs9SigningTime)?.SigningTime;

            try
            {
                signerInfo.CheckSignature(verifySignatureOnly: isVerifyCertificateChain);
            }
            catch (CryptographicException e)
            {
                return(VerifierResponse.Invalid($"Signature is matematically invalid with message : {e.Message}"));
            }

            X509Certificate2 certificate = signerInfo.Certificate;

            if (signingDateTime.HasValue)
            {
                bool isSigningDateValid =
                    signingDateTime.Value <certificate.NotAfter &&
                                           signingDateTime.Value> certificate.NotBefore;

                if (!isSigningDateValid)
                {
                    return(new VerifierResponse()
                    {
                        IsSignatureMathematicallyValid = true,
                        IsSignatureSigningDateValid = false,
                        SigningDateTime = signingDateTime,
                        Message =
                            $"Signature is matematically valid but signing date {signingDateTime.Value} lies outside of certificate validity range [{certificate.NotBefore}, {certificate.NotAfter}]"
                    });
                }
            }
            else
            {
                return(new VerifierResponse()
                {
                    IsSignatureMathematicallyValid = true,
                    IsSignatureSigningDateValid = false,
                    Message = "Can't extract signing DateTime. Unable to check certificate validity on signing date."
                });
            }

            return(VerifierResponse.Valid);
        }
コード例 #3
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);
        }