?
Solved

Help with verifying signature of xml files

Posted on 2011-03-18
20
Medium Priority
?
629 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 12
  • 8
20 Comments
 
LVL 23

Expert Comment

by:wdosanjos
ID: 35166155
How are you signing the XML files?
0
 

Author Comment

by:vcharles
ID: 35166233
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
ID: 35166449
The error occurs in the following line:
  Throw New CryptographicException("Verification failed: No Signature was found in the document.")
0
Automating Your MSP Business

The road to profitability.
Delivering superior services is key to ensuring customer satisfaction and the consequent long-term relationships that enable MSPs to lock in predictable, recurring revenue. What's the best way to deliver superior service? One word: automation.

 

Author Comment

by:vcharles
ID: 35166551
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
ID: 35166674
I'll be trying your code locally.  I suspect the issue is when writing the signed XML.
0
 

Author Comment

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

Expert Comment

by:wdosanjos
ID: 35166901
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
ID: 35167228
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
ID: 35167254
Please disregard my last post, will run more test and get back to you.

Thanks,

V.
0
 
LVL 23

Expert Comment

by:wdosanjos
ID: 35167390
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
 

Author Comment

by:vcharles
ID: 35167701
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
ID: 35167950
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
ID: 35168058
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
ID: 35168106
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
ID: 35168160
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
ID: 35168257
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
ID: 35168322
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
ID: 35171921
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 2000 total points
ID: 35182413
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
ID: 35182706
Thank You!
0

Featured Post

When ransomware hits your clients, what do you do?

MSPs: Endpoint security isn’t enough to prevent ransomware.
As the impact and severity of crypto ransomware attacks has grown, Webroot fought back, not just by building a next-gen endpoint solution capable of preventing ransomware attacks but also by being a thought leader.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When the confidentiality and security of your data is a must, trust the highly encrypted cloud fax portfolio used by 12 million businesses worldwide, including nearly half of the Fortune 500.
This paper addresses the security of Sennheiser DECT Contact Center and Office (CC&O) headsets. It describes the DECT security chain comprised of “Pairing”, “Per Call Authentication” and “Encryption”, which are all part of the standard DECT protocol.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…
Suggested Courses

771 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