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