Click here to Skip to main content
15,877,915 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more: , +
I am having a problem parsing out this xml file using XmlElement, the proposed solutions online suggests work-arounds by referencing SAML methods but that does not work for my xml. Any ideas on how to get the XmlElement of SignatureValue? current error is "Malformed element Signature" at line: "signedXml.LoadXml((XmlElement)nodeList[0]);". And below is a piece of the xml used for this test - with the signature and digest values removed. My thought here is that the xml is not being parsed properly by the XmlElement/nodeList:

XML
<Message xmlns="http://www.blah.com/messaging" version="010" release="006">
   <Header>
      <To Qualifier="blah"</To>
      <From Qualifier="blah"</From>
      <MessageID>93585dc9571b49fda</MessageID>
      <SentTime>2013-08-26T17:27:43.80Z</SentTime>
      <SenderSoftware>
         <SenderSoftwareDeveloper>blahpts</SenderSoftwareDeveloper>
         <SenderSoftwareProduct>Certification Testing</SenderSoftwareProduct>
         <SenderSoftwareVersionRelease>2013</SenderSoftwareVersionRelease>
      </SenderSoftware>
      <PrescriberOrderNumber>blah 2.1 ES</PrescriberOrderNumber>
      <DigitalSignature version="2.0">
         <DigestValue>jblahlwT1Y=</DigestValue>
         <SignatureValue>blahblah</SignatureValue>
         <X509Data>blahblahblah</X509Data>
      </DigitalSignature>
   </Header>
   <Body>



C#
public static void Main(String[] args)
{
    try
    {
        // Create a new CspParameters object to specify
        // a key container.
        CspParameters cspParams = new CspParameters();
        cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";

        // Create a new RSA signing key and save it in the container.
        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

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

        // Load an XML file into the XmlDocument object.
        xmlDoc.PreserveWhitespace = true;
        xmlDoc.Load(args[0]); //("test.xml");

        // Verify the signature of the signed XML.
        Console.WriteLine("Verifying signature...");
        bool result = VerifyXml(xmlDoc, rsaKey);

        // Display the results of the signature verification to
        // the console.
        if (result)
        {
            Console.WriteLine("The XML signature is valid.");
        }
        else
        {
            Console.WriteLine("The XML signature is not valid.");
        }

    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
}




// Verify the signature of an XML file against an asymmetric
// algorithm and return the result.
public static Boolean VerifyXml(XmlDocument Doc, RSA Key)
{
    // Check arguments.
    if (Doc == null)
        throw new ArgumentException("Doc");
    if (Key == null)
        throw new ArgumentException("Key");

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

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


    // Throw an exception if no signature was found.
    if (nodeList.Count <= 0)
    {
        throw new CryptographicException("Verification failed: No Signature was found in the document.");
    }

    // This example only supports one signature for
    // the entire XML document.  Throw an exception
    // if more than one signature was found.
    if (nodeList.Count >= 2)
    {
        throw new CryptographicException("Verification failed: More that one signature was found for the document.");
    }

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

    // Check the signature and return the result.
    return signedXml.CheckSignature(Key);
}


What will make it easier is the following specifications:

1) Calculate the Digest Value of the Plain Text, the plain text is the concatinated value of all fields/values in given xml. This process includes using SHA-1 hash to reduce the ASCII encoded plain text to a unique Digest Value.
2) Decrypt the Signature Value, impotant to mention that the encrypted version of the hash of the signed information. The hash value is also the Digest Value. The sender's private key is what was used to encrypt the digest to create the Signature Value. Signature Value can only be decrypted with the sender's public key which is contained in the digital certificate in the X509Data element.
3) Compare the Digest Value that my code calcualtes to match the Digest Value mentioned in the xml from the decrypted signature if the signature is valid.
4) validating the certificate is required, and a message should only be accepted as valid if it has been signed and verified with a valid digital certificate.
Posted
Updated 3-Sep-13 10:58am
v20
Comments
PIEBALDconsult 23-Aug-13 13:54pm    
Which line is throwing the Exception?
[no name] 23-Aug-13 15:19pm    
I noticed that I missed few more lines of the code, I just added them...
Richard MacCutchan 24-Aug-13 4:43am    
Where is that line in the above code?
[no name] 24-Aug-13 23:53pm    
Sorry about that, here it is: rsa.Decrypt(RSAKeyInfo.Modulus,false);
Richard MacCutchan 25-Aug-13 3:08am    
Well that's two different lines, neither of which appears in your original question. I suggest you use your debugger to diagnose why it cannot find the key, in whichever of these lines the program actually uses.

1 solution

Your question's XML is malformed. You need to fix your XML.
These lines are malformed...
XML
<To Qualifier="blah"</To>
<From Qualifier="blah"</From>

The above should probably be...
XML
<To Qualifier="blah"></To>
<From Qualifier="blah"></From>

These lines are malformed too...
HTML
<SignatureValue>blahblah>
<X509Data>blahblahblah;/X509Data>

... and I'm guessing this is what you want for them...
XML
<SignatureValue>blahblah</SignatureValue>
<X509Data>blahblahblah;</X509Data>
 
Share this answer
 
v2
Comments
[no name] 3-Sep-13 17:01pm    
Thank you for the comments, it is not really the reason, those items you point out were self inflected (such as blah...) and some are related to copy and paste...
I believe the issue is bigger than that, I am guessing the tag name "Header" or "Message" might be throwing it off, the thing here is that I have no way of changing the xml, it is as is (as received from the vendor), what I am really after here is to see of to make signedXml.LoadXml to work properly in loading this xml....
idenizeni 3-Sep-13 17:27pm    
No offense, but there is no point in trying to help if we can't trust the code you posted.

The error you receive, 'Malformed element Signature' is saying your XML is not well formed at the element Signature. I don't even see the Signature element in your XML.
[no name] 3-Sep-13 17:31pm    
I had to manually modify the xml before posting it on this site because it contains information that can't be shared, hence when publishing it online I had to modify few elements.

As far as your second comment, you are right, that is the issue, and that is why since the xml starts with
idenizeni 3-Sep-13 17:42pm    
You could try posting dummy but complete XML that doesn't contain sensitive information. Since the error is related to malformed XML and the XML you posted doesn't contain the complete XML structure (regardless of the details) we can only make guesses. I will say that you should look at the content of your XML, if it contains any of the XML special characters in the node values then you may need to ensure the XML in properly encoded when written. See this link for more information on XML special characters...

http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
[no name] 5-Sep-13 12:43pm    
Here is where the problem takes place: // Load the first <signature>node. signedXml.LoadXml((XmlElement)nodeList[0]); When attempting to load the node list, it seems that the method "LoadXml" expects the element name "Signature" this is based on the fact that the signed XML is supposed to have that element in the xml so that LoadXml can find it, but not all xmls are the same, in my case the xml starts with the element "Message" (see xml posted on top). So the question here how can I load this xml with the first element being Message? Is there an override method that can be written or maybe a different way of doing things such as taking the current xml and create a small xml in memory with the right starting element name of "Signature" then process that instead of the original xml, or even renaming the current parent element "Message" to "Signature" keeping in mind that there the "Header" element that it may need to go... thinking upload...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900