Share via


How to sign an XML and verify the signature with .NET (VB.NET)

Hi all,

Today I'm posting a sample which signs an XML with or without a certificate (PFX file) and verifies the signature, all that with .NET and its SignedXml class. I won't include in the sample the code that VS designer includes when I add the textboxes and buttons used in the code. I don't think that's needed to understand the code.

 

<SAMPLE>

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

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

...

#End Region

    Private Sub SignButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SignButton.Click

        ' Generate a signing key.
        '
        Dim Key As New RSACryptoServiceProvider

        ' Create a new XML document.
        '
        Dim doc As New XmlDocument

        ' Format using white spaces.
        '
        doc.PreserveWhitespace = True

        ' Load the passed XML.
        '
        doc.Load(TextBox2.Text)

        ' Create a SignedXml object.
        '
        Dim signedXml As New SignedXml(doc)

        ' Add the key to the SignedXml document.
        '
        signedXml.SigningKey = Key

        ' Create a reference to be signed.
        '
        Dim reference As New Reference
        reference.Uri = ""

        ' Add a transformation to the reference.
        '
        Dim trns As XmlDsigC14NTransform = New XmlDsigC14NTransform
        reference.AddTransform(trns)

        ' 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)

        ' Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
        '
        Dim keyInfo As New KeyInfo
        keyInfo.AddClause(New RSAKeyValue(CType(Key, RSA)))
        signedXml.KeyInfo = keyInfo

        ' 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.
        '
        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))

        If TypeOf doc.FirstChild Is XmlDeclaration Then
            doc.RemoveChild(doc.FirstChild)
        End If

        ' Show the signature
        '
        ToVerifyTextBox.Text = doc.OuterXml
    End Sub

    Private Sub SignWithCerButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SignWithCerButton.Click

        ' Variables
        '
        Dim bResult As Boolean = False
        Dim pCertContext As IntPtr = IntPtr.Zero
        Dim key As RSA = Nothing
        Dim doc As XmlDocument = Nothing
        Dim signedXml As SignedXml = Nothing
        Dim reference As Reference = Nothing
        Dim trns As XmlDsigC14NTransform = Nothing
        Dim env As XmlDsigEnvelopedSignatureTransform = Nothing
        Dim keyInfo As KeyInfo = Nothing
        Dim xmlDigitalSignature As XmlElement = Nothing
        Dim cert As X509Certificate2 = Nothing
        Dim pass As SecureString = Nothing

        ' Generate a signing key from the subject certificate.
        '
        pass = New SecureString()
        pass.AppendChar("p")
        pass.AppendChar("a")
        pass.AppendChar("s")
        pass.AppendChar("s")
        pass.AppendChar("w")
        pass.AppendChar("o")
        pass.AppendChar("r")
        pass.AppendChar("d")
        cert = New X509Certificate2(TextBox1.Text, pass)
        key = cert.PrivateKey

        ' Create a new XML document.
        '
        doc = New XmlDocument

        ' Format using white spaces.
        '
        doc.PreserveWhitespace = True

        ' Load the passed XML.
        '
        doc.Load(TextBox2.Text)

        ' Create a SignedXml object.
        '
        signedXml = New SignedXml(doc)

        ' Add the key to the SignedXml document.
        '
        signedXml.SigningKey = key

        ' Create a reference to be signed.
        '
        reference = New Reference
        reference.Uri = ""

        ' Add a transformation to the reference.
        '
        trns = New XmlDsigC14NTransform
        reference.AddTransform(trns)

        ' Add an enveloped transformation to the reference.
        '
        env = New XmlDsigEnvelopedSignatureTransform
        reference.AddTransform(env)

        ' Add the reference to the SignedXml object.
        '
        signedXml.AddReference(reference)

        ' Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
        '
        'keyInfo = New KeyInfo
        'keyInfo.AddClause(New RSAKeyValue(CType(Key, RSA)))
        'signedXml.KeyInfo = keyInfo

        ' Create a new KeyInfo object.
        '
        keyInfo = New KeyInfo()

        ' Load the certificate into a KeyInfoX509Data object
        ' and add it to the KeyInfo object.
        keyInfo.AddClause(New KeyInfoX509Data(cert))

        ' Add the KeyInfo object to the SignedXml object.
        signedXml.KeyInfo = keyInfo

        ' Compute the signature.
        '
        signedXml.ComputeSignature()

        ' Get the XML representation of the signature and save
        ' it to an XmlElement object.
        '
        xmlDigitalSignature = signedXml.GetXml()

        ' Append the element to the XML document.
        '
        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))

        If TypeOf doc.FirstChild Is XmlDeclaration Then
            doc.RemoveChild(doc.FirstChild)
        End If

        ' Show the signature
        '
        ToVerifyTextBox.Text = doc.OuterXml

    End Sub
    
    Private Sub VerifyButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles VerifyButton.Click

        ' Create a new XML document.
        '
        Dim xmlDocument As New XmlDocument

        ' Format using white spaces.
        '
        xmlDocument.PreserveWhitespace = True

        ' Load the passed XML file into the document. 
        '
        xmlDocument.LoadXml(ToVerifyTextBox.Text)

        ' Create a new SignedXml object and pass it the XML document class.
        '
        Dim signedXml As New SignedXml(xmlDocument)

        ' Find the "Signature" node and create a new XmlNodeList object.
        '
        Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature", "https://www.w3.org/2000/09/xmldsig#")

        ' Load the signature node.
        '
        signedXml.LoadXml(CType(nodeList(0), XmlElement))

        ' Check the signature and show the result.
        '
        If signedXml.CheckSignature() Then
            MessageBox.Show("Signature verified!")
        Else
            MessageBox.Show("Invalid signature!!!")
        End If

    End Sub
        
End Class

</SAMPLE>

I hope this helps.

Cheers,

 

Alex (Alejandro Campos Magencio)

Comments

  • Anonymous
    April 18, 2008
    OH! Very good , I want it .  Thanks :D
  • Anonymous
    June 03, 2008
    Hi,What i need to sign the same doc multiple times & then try to verify the same ? How would that work ?I tired to simply add one more signature to the signing part with a new key & try to get the same from the next node for verification.In this case the first signature fails but the second one passes. Any clue if wot im doing is right ?
  • Anonymous
    March 25, 2009
    Thanks for helping me on the way with my project!I've written a class for signing and verifying XML with C# .NET 1.1 using CAPICOM: http://blog.sallarp.com/2009/03/verify-xml-signatures-with-net-1-using-capicom/
  • Anonymous
    February 15, 2010
    Thank you very much for you post. I found it very useful.
  • Anonymous
    June 10, 2010
    Hello,Hope you are still reading this. I really enjoyed the example. Got a question tough. How can I retrieve the X509Certificate from the signedXMl document ? I want to check also the attached certificate, not only the signature. I tried with GetElementsByTagName("X509Certificate"). This results in a nodelist of 1 element, but how to cast this or convert this to a X509Certificate object ? I want to match this to a list of allowed issuers.If you have any idea on this, please help me out.Best regards,Ronald
  • Anonymous
    June 13, 2010
    Sorry, I have no free time to attend this kind of requests. If you open a case with Microsoft Technical Support, we may be able to assist.Regards,Alex
  • Anonymous
    October 01, 2015
    Thanks Alex for the  great example, really easy to follow and provided a solid base for an XML signing app I'm working on