Solved

Help with verifying signature of xml files

Posted on 2011-03-18
20
606 Views
Last Modified: 2012-05-11
Hello,

I'm able to sign my xml files, however when loading my project, the code below to verify the xml are signed is not working, I received error message: " Verification Failed: No signature was found in the document". Any idea what's wrong with the code?

Thanks,

Victor

Project Code:

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.CenterToScreen()
        VerifyXML.VerifyXml("Donor.xml")

        VerifyXML.VerifyXml("Receiver.xml")

    End Sub
End Class

***************

Imports System.Security.Cryptography
Imports System.Xml

Module VerifyXML
    Function VerifyXml(ByVal xmlFileName As String) As [Boolean] ' Create a new CspParameters object to specify ' a key container.
        Dim cspParams As New CspParameters()
        cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
        ' Create a new RSA signing key and save it in the container.
        Dim rsaKey As New RSACryptoServiceProvider(cspParams)
        ' Create a new XML document.
        Dim xmlDoc As New XmlDocument()
        ' Load an XML file into the XmlDocument object.
        xmlDoc.PreserveWhitespace = True
        Return VerifyAnXml(xmlDoc, rsaKey)

    End Function
    Function VerifyAnXml(ByVal Doc As XmlDocument, ByVal Key As RSA) As [Boolean] ' Check arguments.
        If Doc Is Nothing Then
            Throw New ArgumentException("Doc")
        End If
        If Key Is Nothing Then
            Throw New ArgumentException("Key")
        End If
        ' Create a new SignedXml object and pass it ' the XML document class.
        Dim signedXml As New SignedXml(Doc)
        ' Find the "Signature" node and create a new ' XmlNodeList object.
        Dim nodeList As XmlNodeList = Doc.GetElementsByTagName("Signature")
        MsgBox(nodeList.Count)
        ' Throw an exception if no signature was found.
        If nodeList.Count <= 0 Then
            Throw New CryptographicException("Verification failed: No Signature was found in the document.")
        End If ' 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 Then
            Throw New CryptographicException("Verification failed: More than one signature was found for the document.")
        End If ' Load the first <signature> node.
        signedXml.LoadXml(CType(nodeList(0), XmlElement)) ' Check the signature and return the result.
        Return signedXml.CheckSignature(Key)
    End Function
End Module
0
Comment
Question by:vcharles
  • 12
  • 8
20 Comments
 
LVL 23

Expert Comment

by:wdosanjos
Comment Utility
How are you signing the XML files?
0
 

Author Comment

by:vcharles
Comment Utility
I am signing the xml with the following code:

Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Xml
Imports System.Windows.Forms

Module Module1
    Sub Main()
        ' Get the user's documents folder.
        '   Dim path As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
        Dim path As String = (Application.StartupPath)
        Sign(path + "\" + "Receiver.xml")
        Sign(path + "\" + "Donor.xml")
    End Sub
    Sub Sign(ByVal xmlFileName As String)
        Try
            ' Create a new CspParameters object to specify
            ' a key container.
            Dim cspParams As New CspParameters()
            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
            ' Create a new RSA signing key and save it in the container.
            Dim rsaKey As New RSACryptoServiceProvider(cspParams)
            ' Create a new XML document.
            Dim xmlDoc As New XmlDocument()

            ' Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load(xmlFileNAme)
            ' Sign the XML document.
            SignXml(xmlDoc, rsaKey)

            Console.WriteLine("XML file signed.")

            ' Save the document.
            xmlDoc.Save(xmlFileNAme)
        Catch e As Exception
            Console.WriteLine(e.Message)
        End Try
    End Sub
    ' Sign an XML file.
    ' This document cannot be verified unless the verifying
    ' code has the key with which it was signed.
    Sub SignXml(ByVal xmlDoc As XmlDocument, ByVal Key As RSA)
        ' Check arguments.
        If xmlDoc Is Nothing Then
            Throw New ArgumentException("xmlDoc")
        End If
        If Key Is Nothing Then
            Throw New ArgumentException("Key")
        End If
        ' Create a SignedXml object.
        Dim signedXml As New SignedXml(xmlDoc)
        ' Add the key to the SignedXml document.
        signedXml.SigningKey = Key
        ' Create a reference to be signed.
        Dim reference As New Reference()
        reference.Uri = ""
        ' Add an enveloped transformation to the reference.
        Dim env As New XmlDsigEnvelopedSignatureTransform()
        reference.AddTransform(env)
        ' Add the reference to the SignedXml object.
        signedXml.AddReference(reference)
        ' Compute the signature.
        signedXml.ComputeSignature()
        ' Get the XML representation of the signature and save
        ' it to an XmlElement object.
        Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
        ' Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
    End Sub

End Module
0
 

Author Comment

by:vcharles
Comment Utility
The error occurs in the following line:
  Throw New CryptographicException("Verification failed: No Signature was found in the document.")
0
 

Author Comment

by:vcharles
Comment Utility
For some reason nodelist.count = 0

The code is supposed to verify each xml file in the Form Load event, but apparently  it doesn't recognize the xml files when verifying the signature. Any idea how to fix that problem?

Thanks,

Victor

 
0
 
LVL 23

Expert Comment

by:wdosanjos
Comment Utility
I'll be trying your code locally.  I suspect the issue is when writing the signed XML.
0
 

Author Comment

by:vcharles
Comment Utility
Thanks for your help, looking forward to hear back from you.
0
 
LVL 23

Expert Comment

by:wdosanjos
Comment Utility
VerifyXml is missing a line to load the XML file:

        Dim xmlDoc As New XmlDocument()
        ' Load an XML file into the XmlDocument object.
        xmlDoc.PreserveWhitespace = True
        xmlDoc.Load(xmlFileName)    ' <<<<<<<<<< This line is missing
        Return VerifyAnXml(xmlDoc, rsaKey)

I think this fixes the issue, as I tried on my end and it's working now.  Please verify.
0
 

Author Comment

by:vcharles
Comment Utility
Do In need to list it multiple times? For example:
xmlDoc.Load(Receiver.xml)
xmlDoc.Load(Donor.xml)

From the load event I'm trying to pass one xml file at a time to verify its signature.

How do I pass the xml files from the Form Load event to xmlDoc.Load?

Thanks,

Victor
0
 

Author Comment

by:vcharles
Comment Utility
Please disregard my last post, will run more test and get back to you.

Thanks,

V.
0
 
LVL 23

Expert Comment

by:wdosanjos
Comment Utility
Here is the complete code including the missing line:

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.CenterToScreen()
        VerifyXML.VerifyXml("Donor.xml")

        VerifyXML.VerifyXml("Receiver.xml")

    End Sub
End Class

Open in new window


Imports System.Security.Cryptography
Imports System.Xml

Module VerifyXML
    Function VerifyXml(ByVal xmlFileName As String) As [Boolean] ' Create a new CspParameters object to specify ' a key container.
        Dim cspParams As New CspParameters()
        cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
        ' Create a new RSA signing key and save it in the container.
        Dim rsaKey As New RSACryptoServiceProvider(cspParams)
        ' Create a new XML document.
        Dim xmlDoc As New XmlDocument()
        ' Load an XML file into the XmlDocument object.
        xmlDoc.PreserveWhitespace = True
        xmlDoc.Load(xmlFileName)    ' <<<<<<<<<< Include this line.
        Return VerifyAnXml(xmlDoc, rsaKey)

    End Function
    Function VerifyAnXml(ByVal Doc As XmlDocument, ByVal Key As RSA) As [Boolean] ' Check arguments.
        If Doc Is Nothing Then
            Throw New ArgumentException("Doc")
        End If
        If Key Is Nothing Then
            Throw New ArgumentException("Key")
        End If
        ' Create a new SignedXml object and pass it ' the XML document class.
        Dim signedXml As New SignedXml(Doc)
        ' Find the "Signature" node and create a new ' XmlNodeList object.
        Dim nodeList As XmlNodeList = Doc.GetElementsByTagName("Signature")
        MsgBox(nodeList.Count)
        ' Throw an exception if no signature was found.
        If nodeList.Count <= 0 Then
            Throw New CryptographicException("Verification failed: No Signature was found in the document.")
        End If ' 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 Then
            Throw New CryptographicException("Verification failed: More than one signature was found for the document.")
        End If ' Load the first <signature> node.
        signedXml.LoadXml(CType(nodeList(0), XmlElement)) ' Check the signature and return the result.
        Return signedXml.CheckSignature(Key)
    End Function
End Module

Open in new window

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:vcharles
Comment Utility
It finds the xml files but I'm getting the following error:
on the code below:

Error: The Method or Operation is not implemented

Sub LoadXml(ByVal xmlElement As Xml.XmlElement)
        Throw New NotImplementedException ' Error Line
    End Sub

Any ideas what's causing this error?

When the program runs, it creates the following class:

Class SignedXml

    Private _doc As XmlDocument

    Sub New(ByVal Doc As XmlDocument)
        ' TODO: Complete member initialization
        _doc = Doc
    End Sub

    Function CheckSignature(ByVal Key As Security.Cryptography.RSA) As Boolean
        Throw New NotImplementedException
    End Function

    Sub LoadXml(ByVal xmlElement As Xml.XmlElement)
        Throw New NotImplementedException
    End Sub

End Class

Thanks,

Victor
0
 
LVL 23

Expert Comment

by:wdosanjos
Comment Utility
I think you are missing Imports and a Reference.  Please follow these steps to fix it:

. Delete the SignedXml class
. Add a reference to System.Security.dll
. Import namespaces System.Security and System.Security.Cryptography

 Imports and Reference
0
 

Author Comment

by:vcharles
Comment Utility
I'm using
Imports System.Security
Imports System.Security.Cryptography
Imports System.Xml

But still getting the same error message. I was able to add System.Security
in the Reference section of Soltion Explorer, but couldn'y System.Security.Cryptography.

0
 
LVL 23

Expert Comment

by:wdosanjos
Comment Utility
Make sure the generated SignedXml class has been deleted.  

Sorry, I missed the following Import:

     System.Security.Cryptography.Xml

Alternatively you can reference the fully qualified class name:

        Dim signedXml As New System.Security.Cryptography.Xml.SignedXml(Doc)
0
 

Author Comment

by:vcharles
Comment Utility
I followed your instrcutions the nodeList.count value starts as = 1 than but for some reason the value became = 0" and I getting the error from the code below:
 If nodeList.Count <= 0 Then
            Throw New CryptographicException("Verification failed: No Signature was found in the document.")
        End If
0
 

Author Comment

by:vcharles
Comment Utility
I created a setup app and ran it within the same folder the other application signed the xml, didn't get any values of 0, but when I made a change to the xml file, the application didn't notice the change and the program ran normally. Not sure if this is related to the previous error from my previous post.
0
 
LVL 23

Expert Comment

by:wdosanjos
Comment Utility
I'm not sure I understand what you are doing.  But, possibly you have multiple copies of these xml files in different folders.  To make sure you are reading the correct file, include the full path on the following statements:

        VerifyXML.VerifyXml("Donor.xml")

        VerifyXML.VerifyXml("Receiver.xml")
0
 

Author Comment

by:vcharles
Comment Utility
I fixed the path issue but the prvious approach didn't work properly because when I made a change to the xml, the program still behaved as if all was ok.

I'm using a new approach with the code below, which works for signing and verify one xml file. How do I modify the code below to sign and verify multiple files?

Code:

Imports System.Security.Cryptography
Imports System
Imports System.Xml
Imports System.Security.Cryptography.Xml

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        ' Sign an XML
        Console.WriteLine("Verifying signature...")
        SignXML.SignXml()
    End Sub

    Private Sub C1Button1_Click(sender As System.Object, e As System.EventArgs) Handles C1Button1.Click
        ' Verify the signature of the signed XML.
        Dim result As Boolean = VerifyXml()
        If result Then
            MsgBox("The XML signature is valid.")
        Else
            MsgBox("The XML signature is not valid.")
        End If
    End Sub

    Private Function VerifyXml() As Boolean
        '  Throw New NotImplementedException
        ' Create a new CspParameters object to specify
        ' a key container.
        Dim cspParams As New Security.Cryptography.CspParameters()
        cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
        ' Create a new RSA signing key and save it in the container.
        Dim rsaKey As New RSACryptoServiceProvider(cspParams)
        ' Create a new XML document.
        Dim xmlDoc As New System.Xml.XmlDocument()
        ' Load an XML file into the XmlDocument object.
        xmlDoc.PreserveWhitespace = True
        xmlDoc.Load("Receiver.xml")
        Return VerifyAnXml(xmlDoc, rsaKey)
    End Function
    Function VerifyAnXml(ByVal Doc As XmlDocument, ByVal Key As RSA) As [Boolean]
        ' Check arguments.
        If Doc Is Nothing Then
            Throw New ArgumentException("Doc")
        End If
        If Key Is Nothing Then
            Throw New ArgumentException("Key")
        End If
        ' Create a new SignedXml object and pass it
        ' the XML document class.
        Dim signedXml As New SignedXml(Doc)
        ' Find the "Signature" node and create a new
        ' XmlNodeList object.
        Dim nodeList As XmlNodeList = Doc.GetElementsByTagName("Signature")
        ' Throw an exception if no signature was found.
        If nodeList.Count <= 0 Then
            Throw New CryptographicException("Verification failed: No Signature was found in the document.")
        End If

        ' 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 Then
            Throw New CryptographicException("Verification failed: More that one signature was found for the document.")
        End If

        ' Load the first <signature> node.  
        signedXml.LoadXml(CType(nodeList(0), XmlElement))
        ' Check the signature and return the result.
        Return signedXml.CheckSignature(Key)
    End Function

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

    End Sub
End Class


Module:

Imports System
Imports System.Security.Cryptography
Imports System.Xml
Imports System.Security.Cryptography.Xml

Module SignXML
    Sub SignXml()
        Try
            ' Create a new CspParameters object to specify
            ' a key container.
            Dim cspParams As New CspParameters()
            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
            ' Create a new RSA signing key and save it in the container.
            Dim rsaKey As New RSACryptoServiceProvider(cspParams)
            ' Create a new XML document.
            Dim xmlDoc As New XmlDocument()

            ' Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load("Receiver.xml")
            ' Sign the XML document.
            SignAnXml(xmlDoc, rsaKey)

            MsgBox("XML file signed.")

            ' Save the document.
            xmlDoc.Save("Receiver.xml")

        Catch e As Exception
            Console.WriteLine(e.Message)
        End Try
    End Sub

Sub SignAnXml(ByVal xmlDoc As XmlDocument, ByVal Key As RSA)
        ' Check arguments.
        If xmlDoc Is Nothing Then
            Throw New ArgumentException("xmlDoc")
        End If
        If Key Is Nothing Then
            Throw New ArgumentException("Key")
        End If
        ' Create a SignedXml object.
        Dim signedXml As New SignedXml(xmlDoc)
        ' Add the key to the SignedXml document.
        signedXml.SigningKey = Key
        ' Create a reference to be signed.
        Dim reference As New Reference()
        reference.Uri = ""
        ' Add an enveloped transformation to the reference.
        Dim env As New XmlDsigEnvelopedSignatureTransform()
        reference.AddTransform(env)
        ' Add the reference to the SignedXml object.
        signedXml.AddReference(reference)
        ' Compute the signature.
        signedXml.ComputeSignature()
        ' Get the XML representation of the signature and save
        ' it to an XmlElement object.
        Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
        ' Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
    End Sub
End Module


Thanks
0
 
LVL 23

Accepted Solution

by:
wdosanjos earned 500 total points
Comment Utility
You should be able to do as follows. I just added a xmlFile parameter to SignXml and VerifyXml functions.

Code
Imports System.Security.Cryptography
Imports System
Imports System.Xml
Imports System.Security.Cryptography.Xml

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        ' Sign an XML
        Console.WriteLine("Verifying signature...")
        SignXML.SignXml("Receiver.xml")
        SignXML.SignXml("Donor.xml")
    End Sub

    Private Sub C1Button1_Click(sender As System.Object, e As System.EventArgs) Handles C1Button1.Click
        ' Verify the signature of the signed XML.
        Dim result As Boolean = VerifyXml("Receiver.xml")
        If result Then
            MsgBox("The XML signature is valid.")
        Else
            MsgBox("The XML signature is not valid.")
        End If

        ' Verify the signature of the signed XML.
        Dim result As Boolean = VerifyXml("Donor.xml")
        If result Then
            MsgBox("The XML signature is valid.")
        Else
            MsgBox("The XML signature is not valid.")
        End If
    End Sub

    Private Function VerifyXml(xmlFile As String) As Boolean
        '  Throw New NotImplementedException
        ' Create a new CspParameters object to specify
        ' a key container.
        Dim cspParams As New Security.Cryptography.CspParameters()
        cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
        ' Create a new RSA signing key and save it in the container.
        Dim rsaKey As New RSACryptoServiceProvider(cspParams)
        ' Create a new XML document.
        Dim xmlDoc As New System.Xml.XmlDocument()
        ' Load an XML file into the XmlDocument object.
        xmlDoc.PreserveWhitespace = True
        xmlDoc.Load(xmlFile)
        Return VerifyAnXml(xmlDoc, rsaKey)
    End Function
    Function VerifyAnXml(ByVal Doc As XmlDocument, ByVal Key As RSA) As [Boolean]
        ' Check arguments.
        If Doc Is Nothing Then
            Throw New ArgumentException("Doc")
        End If
        If Key Is Nothing Then
            Throw New ArgumentException("Key")
        End If
        ' Create a new SignedXml object and pass it
        ' the XML document class.
        Dim signedXml As New SignedXml(Doc)
        ' Find the "Signature" node and create a new
        ' XmlNodeList object.
        Dim nodeList As XmlNodeList = Doc.GetElementsByTagName("Signature")
        ' Throw an exception if no signature was found.
        If nodeList.Count <= 0 Then
            Throw New CryptographicException("Verification failed: No Signature was found in the document.")
        End If

        ' 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 Then
            Throw New CryptographicException("Verification failed: More that one signature was found for the document.")
        End If

        ' Load the first <signature> node.  
        signedXml.LoadXml(CType(nodeList(0), XmlElement))
        ' Check the signature and return the result.
        Return signedXml.CheckSignature(Key)
    End Function

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

    End Sub
End Class

Open in new window


Module
Imports System
Imports System.Security.Cryptography
Imports System.Xml
Imports System.Security.Cryptography.Xml

Module SignXML
    Sub SignXml(xmlFile As String)
        Try
            ' Create a new CspParameters object to specify
            ' a key container.
            Dim cspParams As New CspParameters()
            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
            ' Create a new RSA signing key and save it in the container.
            Dim rsaKey As New RSACryptoServiceProvider(cspParams)
            ' Create a new XML document.
            Dim xmlDoc As New XmlDocument()

            ' Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load(xmlFile)
            ' Sign the XML document.
            SignAnXml(xmlDoc, rsaKey)

            MsgBox("XML file signed.")

            ' Save the document.
            xmlDoc.Save(xmlFile)

        Catch e As Exception
            Console.WriteLine(e.Message)
        End Try
    End Sub

Sub SignAnXml(ByVal xmlDoc As XmlDocument, ByVal Key As RSA)
        ' Check arguments.
        If xmlDoc Is Nothing Then
            Throw New ArgumentException("xmlDoc")
        End If
        If Key Is Nothing Then
            Throw New ArgumentException("Key")
        End If
        ' Create a SignedXml object.
        Dim signedXml As New SignedXml(xmlDoc)
        ' Add the key to the SignedXml document.
        signedXml.SigningKey = Key
        ' Create a reference to be signed.
        Dim reference As New Reference()
        reference.Uri = ""
        ' Add an enveloped transformation to the reference.
        Dim env As New XmlDsigEnvelopedSignatureTransform()
        reference.AddTransform(env)
        ' Add the reference to the SignedXml object.
        signedXml.AddReference(reference)
        ' Compute the signature.
        signedXml.ComputeSignature()
        ' Get the XML representation of the signature and save
        ' it to an XmlElement object.
        Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
        ' Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
    End Sub
End Module

Open in new window

0
 

Author Closing Comment

by:vcharles
Comment Utility
Thank You!
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

By default, Carbonite Server Backup manages your encryption key for you using Advanced Encryption Standard (AES) 128-bit encryption. If you choose to manage your private encryption key, your backups will be encrypted using AES 256-bit encryption.
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now