예제 #1
0
        public ValidationError DigestValueVerificationHandler(XmlDocument xmlDoc, string xmlFileName)
        {
            ValidationError validationError = new ValidationError(xmlFileName, null);

            if (!ValidationEnums.ReferenceTypeConstraints.Mappings.ContainsKey("ds:Manifest"))
            {
                return(validationError.AppendErrorMessage("Signature reference type was not found."));
            }

            var referenceType = ValidationEnums.ReferenceTypeConstraints.Mappings["ds:Manifest"];

            var referencesNodes = xmlDoc.SelectXmlNodes($"//ds:Signature/ds:SignedInfo/ds:Reference[@Type='{referenceType}']");

            foreach (XmlNode refNode in referencesNodes)
            {
                string uriTarget = refNode.AtrValue("URI")?.Substring(1);

                var manifestNode = xmlDoc.SelectXmlNode($"//ds:Manifest[@Id='{uriTarget}']");

                if (manifestNode == null)
                {
                    return(validationError.AppendErrorMessage($"Couldnt find Manifest element with id : {uriTarget}."));
                }

                // Reference digest method
                string digestAlgorithm = refNode.SelectXmlNode("//ds:DigestMethod")?.AtrValue("Algorithm");

                if (!ValidationEnums.HashAlgorithms.SHAMappings.ContainsKey(digestAlgorithm))
                {
                    return(validationError.AppendErrorMessage($"Invalid digest method algorithm : {digestAlgorithm}"));
                }

                var transformNodes = refNode.SelectXmlNodes("ds:Transforms/ds:Transform");

                // Should be only one algorithm (Canonicalization - omit comments)
                foreach (XmlNode transformNode in transformNodes)
                {
                    string transformAlgorithm = transformNode.AtrValue("Algorithm");

                    if (transformAlgorithm != ValidationEnums.Canonicalization.CanonicalizationMethod)
                    {
                        return(validationError.AppendErrorMessage($"Invalid transform algorithm : {transformAlgorithm}"));
                    }

                    var    outputArray = CanonicalizationHelper.CanonicalizeXmlDigest(manifestNode, ValidationEnums.HashAlgorithms.SHAMappings[digestAlgorithm]);
                    string digestOutputBase64String = Convert.ToBase64String(outputArray);

                    // Retrieve expected digest
                    string xmlDigestValueBase64String = refNode.SelectXmlNode("ds:DigestValue")?.InnerText;

                    if (digestOutputBase64String != xmlDigestValueBase64String)
                    {
                        return(validationError.AppendErrorMessage("Digest values do not match."));
                    }
                }
            }

            return(validationError);
        }
        public ValidationError ValidateManifestReference(XmlDocument xmlDoc, string xmlFileName)
        {
            ValidationError validationError = new ValidationError(xmlFileName, null);

            XmlNodeList manifestReferences = xmlDoc.SelectXmlNodes("//ds:Signature/ds:Object/ds:Manifest/ds:Reference");

            foreach (XmlNode manifestRef in manifestReferences)
            {
                var     refURI           = manifestRef.AtrValue("URI")?.Substring(1);
                XmlNode referencedObject = xmlDoc.SelectXmlNode($"ds:Object[@Id='{refURI}']");

                if (referencedObject == null)
                {
                    return(validationError.AppendErrorMessage("Referenced object does not exist"));
                }

                byte[] referencedElementByte = CanonicalizationHelper.CanonicalizeXml(referencedObject);

                string refStr = Encoding.UTF8.GetString(referencedElementByte);

                XmlNodeList transforms = manifestRef.SelectXmlNodes("ds:Transforms/ds:Transform");
                string      digestAlgo = manifestRef.SelectXmlNode("ds:DigestMethod")?.AtrValue("Algorithm");
                string      digestOutputBase64String = null;

                foreach (XmlNode transformEle in transforms)
                {
                    string transformAlgo = transformEle.AtrValue("Algorithm");

                    if (transformAlgo == ValidationEnums.Canonicalization.CanonicalizationMethod)
                    {
                        var hashAlgo    = ValidationEnums.HashAlgorithms.SHAMappings[digestAlgo];
                        var outputArray = CanonicalizationHelper.CanonicalizeXmlDigest(referencedObject, hashAlgo);

                        digestOutputBase64String = Convert.ToBase64String(outputArray);
                    }
                    else if (transformAlgo == "http://www.w3.org/2000/09/xmldsig#base64")
                    {
                        digestOutputBase64String = Encoding.UTF8.GetString(Convert.FromBase64String(Encoding.UTF8.GetString(referencedElementByte)));
                    }
                    else
                    {
                        return(validationError.AppendErrorMessage($"Not supported transform algorithm :  {transformAlgo}"));
                    }

                    string digestValue = manifestRef.SelectXmlNode("ds:DigestValue")?.InnerText;

                    if (digestValue != digestOutputBase64String)
                    {
                        return(validationError.AppendErrorMessage($"ds:DigestValue values do not match {digestValue}  <-> {digestOutputBase64String}"));
                    }
                    else
                    {
                        ;
                    }
                }
            }
            return(validationError);
        }
예제 #3
0
        public ValidationError SignatureValueVerificationHandler(XmlDocument xmlDoc, string xmlFileName)
        {
            ValidationError validationError = new ValidationError(xmlFileName, null);

            var signedInfoElement             = xmlDoc.SelectXmlNode("//ds:Signature/ds:SignedInfo");
            var signatureMethodElement        = xmlDoc.SelectXmlNode("//ds:Signature/ds:SignedInfo/ds:SignatureMethod");
            var canonicalizationMethodElement = xmlDoc.SelectXmlNode("//ds:Signature/ds:SignedInfo/ds:CanonicalizationMethod");
            var signatureValueElement         = xmlDoc.SelectXmlNode("//ds:Signature/ds:SignatureValue");

            if (signatureValueElement == null)
            {
                return(validationError.AppendErrorMessage(nameof(signatureValueElement) + " missing"));
            }
            if (signatureMethodElement == null)
            {
                return(validationError.AppendErrorMessage(nameof(signatureMethodElement) + " missing"));
            }
            if (canonicalizationMethodElement == null)
            {
                return(validationError.AppendErrorMessage(nameof(canonicalizationMethodElement) + " missing"));
            }
            if (signedInfoElement == null)
            {
                return(validationError.AppendErrorMessage(nameof(signedInfoElement) + " missing"));
            }

            var certificate = XmlNodeHelper.GetX509Certificate(xmlDoc);

            if (certificate == null)
            {
                return(validationError.AppendErrorMessage("X509Certificate element is missing"));
            }

            var canMethod = canonicalizationMethodElement.AtrValue("Algorithm");

            if (canMethod != ValidationEnums.Canonicalization.CanonicalizationMethod)
            {
                return(validationError.AppendErrorMessage($"Not supported cannonicalization method. {canMethod}"));
            }

            var digestBytes = CanonicalizationHelper.CanonicalizeXml(signedInfoElement);

            string singnatureAlgorithm = signatureMethodElement.AtrValue("Algorithm");

            if (!ValidationEnums.Cryptography.SupportedSignatureSchemasMappings.ContainsKey(singnatureAlgorithm))
            {
                return(validationError.AppendErrorMessage($"Not supported signing algorithm {singnatureAlgorithm}"));
            }

            var signingAlgo = ValidationEnums.Cryptography.SupportedSignatureSchemasMappings[singnatureAlgorithm];

            AsymmetricKeyParameter publicKey = certificate.GetPublicKey();
            ISigner signer = SignerUtilities.GetSigner(signingAlgo);

            signer.Init(false, publicKey);
            signer.BlockUpdate(digestBytes, 0, digestBytes.Length);

            if (!signer.VerifySignature(Convert.FromBase64String(signatureValueElement.InnerText)))
            {
                return(validationError.AppendErrorMessage("Cannot verify signature with publick key."));
            }

            return(validationError);
        }