Open federico-66 opened 6 years ago
Hi,
Replace "CheckDigestedReferences" method with this code:
private bool CheckDigestedReferences()
{
ArrayList references = m_signature.SignedInfo.References;
Assembly System_Security_Assembly = Assembly.Load("System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
Type CanonicalXmlNodeList_Type = System_Security_Assembly.GetType("System.Security.Cryptography.Xml.CanonicalXmlNodeList");
ConstructorInfo CanonicalXmlNodeList_Constructor = CanonicalXmlNodeList_Type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
MethodInfo CanonicalXmlNodeList_Add = CanonicalXmlNodeList_Type.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);
Object refList = CanonicalXmlNodeList_Constructor.Invoke(null);
CanonicalXmlNodeList_Add.Invoke(refList, new object[] { this.signatureDocument });
Type Reference_Type = typeof(Reference);
MethodInfo Reference_CalculateHashValue = Reference_Type.GetMethod("CalculateHashValue", BindingFlags.NonPublic | BindingFlags.Instance);
for (int i = 0; i < references.Count; ++i)
{
Reference digestedReference = (Reference)references[i];
byte[] calculatedHash = (byte[])Reference_CalculateHashValue.Invoke(digestedReference, new object[] { this.signatureDocument, refList });
if (calculatedHash.Length != digestedReference.DigestValue.Length)
return false;
byte[] rgb1 = calculatedHash;
byte[] rgb2 = digestedReference.DigestValue;
for (int j = 0; j < rgb1.Length; ++j)
{
if (rgb1[j] != rgb2[j]) return false;
}
}
return true;
}
I need to test it in deep but I think this will works for you... please try it and let me know if works fine to upload the fix later.
I think this issue also affects to enveloped signatures validation.
I'm sorry, but it does not solve the problem. The error is generated when the CalculateHashValue method is invoked! I tried to modify the xpathExpression, removing the namespace and validation is ok !!! This is the StackTrace of the InnerException:
in MS.Internal.Xml.XPath.CompiledXpathExpr.UndefinedXsltContext.LookupNamespace(String prefix)
in MS.Internal.Xml.XPath.BaseAxisQuery.SetXsltContext(XsltContext context)
in MS.Internal.Xml.XPath.BooleanFunctions.SetXsltContext(XsltContext context)
in MS.Internal.Xml.XPath.BooleanFunctions.SetXsltContext(XsltContext context)
in MS.Internal.Xml.XPath.BooleanFunctions.SetXsltContext(XsltContext context)
in MS.Internal.Xml.XPath.CompiledXpathExpr.SetContext(IXmlNamespaceResolver nsResolver)
in MS.Internal.Xml.XPath.CompiledXpathExpr.SetContext(XmlNamespaceManager nsManager)
==>> in System.Security.Cryptography.Xml.XmlDsigXPathTransform.GetOutput() <<==
in System.Security.Cryptography.Xml.TransformChain.TransformToOctetStream(Object inputObject, Type inputType, XmlResolver resolver, String baseUri)
in System.Security.Cryptography.Xml.TransformChain.TransformToOctetStream(XmlDocument document, XmlResolver resolver, String baseUri)
in System.Security.Cryptography.Xml.Reference.CalculateHashValue(XmlDocument document, CanonicalXmlNodeList refList)" string
I'm not an expert, but it seems that XmlDsigXPathTransform.GetOutput() return xml without namespace.
Thanks anyway
Ah ok...sorry, I think I forgot to send you something else...in my test case with an enveloped signature with an xpath transformation like yours, the validation is ok.
The problem is the namespace propagation...you can try before calculate the hash to add in the reference's PropagatedNameSpaces property the "ds" namespace.
Tomorrow I will review this...
Hi,
Replace "CheckXmldsigSignature" method by this one:
public virtual bool CheckXmldsigSignature()
{
bool retVal = false;
IEnumerable<XmlAttribute> namespaces = GetAllNamespaces(GetSignatureElement());
if (this.KeyInfo == null)
{
KeyInfo keyInfo = new KeyInfo();
X509Certificate xmldsigCert = GetSigningCertificate();
keyInfo.AddClause(new KeyInfoX509Data(xmldsigCert));
this.KeyInfo = keyInfo;
}
SignatureDescription description = CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription;
if (description == null)
{
if (this.SignedInfo.SignatureMethod == "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256")
{
CryptoConfig.AddAlgorithm(typeof(Microsoft.Xades.RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
}
else if (this.SignedInfo.SignatureMethod == "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
{
CryptoConfig.AddAlgorithm(typeof(Microsoft.Xades.RSAPKCS1SHA512SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512");
}
}
foreach (Reference reference in SignedInfo.References)
{
foreach (System.Security.Cryptography.Xml.Transform transform in reference.TransformChain)
{
if (transform.GetType() == typeof(XmlDsigXPathTransform))
{
Type transform_Type = typeof(XmlDsigXPathTransform);
FieldInfo nsm_FieldInfo = transform_Type.GetField("_nsm", BindingFlags.NonPublic | BindingFlags.Instance);
XmlNamespaceManager nsm = (XmlNamespaceManager)nsm_FieldInfo.GetValue(transform);
foreach (var ns in namespaces)
{
nsm.AddNamespace(ns.LocalName, ns.Value);
}
}
}
}
retVal = this.CheckDigestedReferences();
if (retVal == false)
{
throw new CryptographicException("CheckXmldsigSignature() failed");
}
var key = this.GetPublicKey();
retVal = this.CheckSignedInfo(key);
if (retVal == false)
{
throw new CryptographicException("CheckXmldsigSignature() failed");
}
return retVal;
}
I hope this helps you...
Problem solved, thanks :-) and thank you very much for sharing the project
Great!!...
very great, thanks again :-)
If you want to sign using a xpath transformation like this, is already necessary to add this code in BuildDigestedReferences(), before call Reference_UpdateHashValue.Invoke.
Hi, I have problems validating the signature when there is an xpath transformation like this:
The following validation generates the error: "The namespace prefix 'ds' is not defined"
If validate the signed xml with third-party software, validation is ok
If remove the xpath transformation, validation is ok.
TIA