Xml Signature for XmlElement fails to verify

前端 未结 1 1418
攒了一身酷
攒了一身酷 2021-01-15 17:49

I apologize in advance for the rather lengthy block of code, but it\'s the smallest compilable example I could produce. I already omitted all error checking from the origina

相关标签:
1条回答
  • 2021-01-15 18:02

    You have a bug in your test code. The second foreach loops again over xmlDoc instead of signedDoc. Fixing this will change the outcome to fail for all nodes.
    Why they fail I don't yet know.


    I couldn't find out why they fail with your code but I found a way to make it work. The difference: All signatures are direct childs of the root element:

    public static void Main()
    {
    
        // ...
    
        var signedDoc = new XmlDocument { PreserveWhitespace = true };
    
        signedDoc.Load("test_signed.xml");
    
        foreach (XmlElement root in signedDoc.GetElementsByTagName("PackageRoot"))
        {
            foreach (XmlElement signature in root.GetElementsByTagName("Signature"))
            {
                var success = signature.VerifySignature(certificate);
                Console.WriteLine(success ? " successful!" : " failed!");
            }
        }
    
        Console.WriteLine("Done.");
        Console.ReadLine();
    }
    
    public static void Sign(this XmlElement element, X509Certificate2 certificate)
    {
        var identifier = Guid.NewGuid().ToString("N");
        element.SetAttribute("Id", identifier);
    
        var signedXml = new SignedXml(element) { SigningKey = certificate.PrivateKey };
        signedXml.AddReference(new Reference("#" + identifier));
        signedXml.ComputeSignature();
    
        var xmlDigitalSignature = signedXml.GetXml();
    
        element.OwnerDocument.DocumentElement.AppendChild(
            element.OwnerDocument.ImportNode(xmlDigitalSignature, true));
    }
    
    public static bool VerifySignature(this XmlElement element, X509Certificate2 certificate)
    {
        var signedXml = new SignedXml(element.OwnerDocument);
        signedXml.LoadXml(element);
    
        return signedXml.CheckSignature(certificate, true);
    }
    

    One important detail to notice: PreserveWhitespace needs to be set to true for signedDoc, too.

    0 讨论(0)
提交回复
热议问题