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"));
        }
Ejemplo n.º 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);
        }