c# - Xml Signature for XmlElement fails to verify -


i apologize in advance rather lengthy block of code, it's smallest compilable example produce. omitted error checking original code. i'm using visual studio 2012 , .net 4.5, although nothing new 4.5, should work version.

i trying sign xml documents' elements protect them tampering. don't want protect whole document, elements. maybe different elements different keys.

however, when sign 3 example elements , try verify them, first 1 verifies, other 2 fail. make worse, first 1 succeeds if modify after being signed. have googled lot, read lot of tutorials , asked theoretical question here, don't have clue i'm doing wrong. can spot mistake?

note: i'd more happy offer same bounty that's on friday's question solving this.

the certificate created executing:

"c:\program files (x86)\microsoft sdks\windows\v7.1a\bin\makecert" -r -pe -n "cn=xmldsig_test" -b 01/01/2013 -e 01/01/2014 -sky signing -ss my

the test xml file is:

<?xml version="1.0" encoding="utf-8" ?> <packageroot>   <package>     <changes >      <change/>     </changes>   </package>   <package>     <changes>      <change/>      <change/>     </changes>   </package>   <package>     <changes>      <change/>      <change/>      <change/>     </changes>   </package> </packageroot> 

the code sign , verify:

namespace soexample {   using system;   using system.security.cryptography.x509certificates;   using system.security.cryptography.xml;   using system.xml;    public static class program   {     public static void sign(this xmlelement element, x509certificate2 certificate)     {         var identifier = guid.newguid().tostring();          element.setattribute("id", identifier);          var signedxml = new signedxml(element) { signingkey = certificate.privatekey };          var reference = new reference("#" + identifier);          reference.addtransform(new xmldsigenvelopedsignaturetransform());          signedxml.addreference(reference);          signedxml.computesignature();          var xmldigitalsignature = signedxml.getxml();          element.appendchild(element.ownerdocument.importnode(xmldigitalsignature, true));     }      public static bool verifysignature(this xmlelement element, x509certificate2 certificate)     {       var signedxml = new signedxml(element);        xmlnodelist nodelist = element.getelementsbytagname("signature");        if (nodelist.count != 1) return false;        signedxml.loadxml((xmlelement)nodelist[0]);        return signedxml.checksignature(certificate, true);     }      public static void main()     {         var xmldoc = new xmldocument { preservewhitespace = true };          xmldoc.load("examplepackage.xml");          var certificate = getcertificatebysubject("cn=xmldsig_test");          foreach (xmlelement root in xmldoc.getelementsbytagname("packageroot"))         {           foreach (xmlelement package in root.getelementsbytagname("package"))           {             package.sign(certificate);           }         }          xmldoc.save("test_signed.xml");          console.writeline("xml file signed.");         console.writeline("press key verify");         console.readline();          var signeddoc = new xmldocument();          signeddoc.load("test_signed.xml");          foreach (xmlelement root in xmldoc.getelementsbytagname("packageroot"))         {           foreach (xmlelement package in root.getelementsbytagname("package"))           {             console.write("verifying package " + package.getattribute("id"));             var success = package.verifysignature(certificate);             console.writeline(success ? " successful!" : " failed!");           }         }          console.writeline("done.");         console.readline();     }      private static x509certificate2 getcertificatebysubject(string certificatesubject)     {       var store = new x509store("my", storelocation.currentuser);        store.open(openflags.readonly | openflags.openexistingonly);        foreach (x509certificate2 c in store.certificates)       {         if (c.subject == certificatesubject)         {           store.close();           return c;         }       }        store.close();       return null;     }   } } 

you have bug in test code. second foreach loops again on xmldoc instead of signeddoc. fixing change outcome fail nodes.
why fail don't yet know.


i couldn't find out why fail code found way make work. difference: signatures direct childs of 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 notice: preservewhitespace needs set true signeddoc, too.


Comments

Popular posts from this blog

c# - DetailsView in ASP.Net - How to add another column on the side/add a control in each row? -

javascript - firefox memory leak -

Trying to import CSV file to a SQL Server database using asp.net and c# - can't find what I'm missing -