Decrypt my World

Cryptography, Security, Debugging and more!

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

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

  • Comments 6

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", "http://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)

  • OH! Very good , I want it .  Thanks :D

  • 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 ?

  • 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/

  • Thank you very much for you post. I found it very useful.

  • 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

  • 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

Page 1 of 1 (6 items)
Leave a Comment
  • Please add 4 and 3 and type the answer here:
  • Post
Translate This Page