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)