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); }
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); }