简体   繁体   中英

XAdES SignedXml.CheckSignature() always returns false

I have used below methods from MSDN for signing and verifying an XML file.

The problem is that I am not able to verify the signed XML file. The SignedXML.CheckSignature() method always returns false, and not even throwing any exception on what went wrong.

Method used to sign XML file

public static void SignXMLFile(XmlDocument xmlDoc, string XmlSigFileName)
{
    // Create a SignedXml object.
    SignedXml signedXml = new SignedXml(xmlDoc);

    string certPath = @"path to PFX file.pfx";

    X509Certificate2 cert = new X509Certificate2(certPath, "password", X509KeyStorageFlags.Exportable);

    var exportedKeyMaterial = cert.PrivateKey.ToXmlString(true);

    var Key = new RSACryptoServiceProvider(new CspParameters(24));
    Key.PersistKeyInCsp = false;

    Key.FromXmlString(exportedKeyMaterial);

    // Assign the key to the SignedXml object.
    signedXml.SigningKey = Key;

    //// Create a reference to be signed.
    //Reference reference = new Reference(System.IO.File.Open(@"D:\test.docx",System.IO.FileMode.Open));

    //// Add the passed URI to the reference object.
    //reference.Uri = URIString;

    //// Add the reference to the SignedXml object.
    //signedXml.AddReference(reference);


    // Create a reference to be signed.
    Reference reference = new Reference();

    // Add the passed URI to the reference object.
    reference.Uri = "";

    // Add the reference to the SignedXml object.
    signedXml.AddReference(reference);

    //Save the public key into the KeyValue node of the Signature
    KeyInfo keyInfo = new KeyInfo();
    keyInfo.AddClause(new RSAKeyValue(Key));
    signedXml.KeyInfo = keyInfo;

    // Compute the signature.
    signedXml.ComputeSignature();

    // Get the XML representation of the signature and save
    // it to an XmlElement object.
    XmlElement xmlDigitalSignature = signedXml.GetXml();

    // Save the signed XML document to a file specified
    //using the passed string.
    XmlTextWriter xmltw = new XmlTextWriter(XmlSigFileName, new UTF8Encoding(false));
    xmlDigitalSignature.WriteTo(xmltw);
    xmltw.Close();

}

Method used to Verify signature of a XML file

// Verify the signature of an XML file and return the result.
public static Boolean VerifyXmlFile(String Name)
{
    // Check the arguments.  
    if (Name == null)
        throw new ArgumentNullException("Name");

    // Create a new XML document.
    XmlDocument xmlDocument = new XmlDocument();

    // Format using white spaces.
    xmlDocument.PreserveWhitespace = true;

    // Load the passed XML file into the document. 
    xmlDocument.Load(Name);

    // Create a new SignedXml object and pass it
    // the XML document class.
    SignedXml signedXml = new SignedXml(xmlDocument);

    // Find the "Signature" node and create a new
    // XmlNodeList object.
    XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");

    // Load the signature node.
    signedXml.LoadXml((XmlElement)nodeList[0]);

    signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigBase64TransformUrl;

    X509Certificate2 cert = new X509Certificate2(@"path to PFX file.pfx", "password");

    // Check the signature and return the result.
    return signedXml.CheckSignature(cert, true);
}

I tried with all the suggesstions from stackoverflow, but no luck. Any help here is much appreciated. Thanks.

Based on data from the comments, your problem is you were trying to use an external (detached) signature, despite the code that you showed using a Uri of "" , which represents "this entire document".

In the Remarks section for SignedXml on MSDN we get a couple of gems:

There is also a fourth kind of signature called an external detached signature which is when the data and signature are in separate XML documents. External detached signatures are not supported by the SignedXml class.

...

The URI attribute of the <Reference> element

...

  • Setting the URI attribute to an empty string indicates that the root element of the document is being signed, a form of enveloped signature.

...

  • Anything else is considered an external resource detached signature and is not supported by the SignedXml class.

And then there's an entire section called "The problem with external references". That section gives a link to After you apply security update 3141780, .NET Framework applications encounter exception errors or unexpected failures while processing files that contain SignedXml .

That link talks about a registry key (which I'm not going to post here, feel free to follow it) which says how to opt out of that particular portion of the MS16-035 security fixes. It also carries with it a note:

Warning Enabling this registry key could allow security vulnerabilities including Denial of Service, Distributed Reflection Denial of Service, Information Disclosure, Signature Bypass, and Remote Code Execution.

So, if you need to do it... be careful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM