X509Certificate Enveloped Signing XML
Couple of days back I was asked to research on Cryptography in .NET Framework v1.1 to digitally sign a document Here is the code which I developed using VB.NET to sign XML file
*******************************************************************
Dim store As WSE.X509CertificateStore
        Dim MyCert As System.Security.Cryptography.X509Certificates.X509Certificate
        store = WSE.X509CertificateStore.CurrentUserStore(WSE.X509CertificateStore.MyStore)
        store.OpenRead()
        For Each cert As X509Certificate In store.Certificates
            MyCert = DirectCast(cert, System.Security.Cryptography.X509Certificates.X509Certificate)
        Next
        store.Close()
        ' using a detached signature. It then verifies  
        ' the signed XML.
        '
        ' The URI to sign.
        Dim resourceToSign As String = "#MyObjectId"
        ' The name of the file to which to save the XML signature.
        Dim XmlFileName As String = "C:\xmldsig.xml"
        Try
            Dim FILE As String = "c:\File.doc"
            Dim Key As New RSACryptoServiceProvider
            Dim prm As RSAParameters = Key.ExportParameters(True)
            ' Sign the detached resource and save the signature in an XML file.
            SignResource(FILE, resourceToSign, XmlFileName, Key, MyCert)
            Key.ImportParameters(prm)
            MsgBox(VerifyXmlFile(FILE, XmlFileName, prm))
        Catch ex As CryptographicException
            Console.WriteLine(ex.Message)
        End Try
*******************************************************************
    ' Sign an XML file and save the signature in a new file.
    Public Sub SignResource(ByVal OriginalFile As String, ByVal URIString As String, ByVal XmlSigFileName As String, ByVal Key As RSA, ByVal Certificate As WSE.X509Certificate)
        ' Create the XmlDocument.
        Dim doc As XmlDocument = New XmlDocument
        doc.LoadXml("<FileInfo></FileInfo>")
        ' Add a price element.
        Dim newElem As XmlElement = doc.CreateElement("Hash")
        'Generate the Hash
        newElem.InnerText = GetHash(OriginalFile)
        doc.DocumentElement.AppendChild(newElem)
        ' Create a SignedXml object.
        Dim signedXml As New SignedXml(doc)
        ' Create a data object to hold the data to sign.
        Dim dataObject As New DataObject
        dataObject.Data = doc.ChildNodes
        dataObject.Id = "MyObjectId"
        ' Add the data object to the signature.
        signedXml.AddObject(dataObject)
        ' Assign the key to the SignedXml object.
        signedXml.SigningKey = Key
        ' Create a reference to be signed.
        Dim reference As New Reference
        '' Add the passed URI to the reference object.
        reference.Uri = URIString
        ' Add the reference to the SignedXml object.
        signedXml.AddReference(reference)
        ' Create a new KeyInfo object.
        Dim keyInfo As New KeyInfo
        ' Load the certificate into a KeyInfoX509Data object
        ' and add it to the KeyInfo object.
        keyInfo.AddClause(New KeyInfoX509Data(Certificate))
        ' 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.
        Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
        doc.DocumentElement.AppendChild(signedXml.GetXml())
        ' Save the document to a file and auto-indent the output.
        Dim writer As XmlTextWriter = New XmlTextWriter("test.xml", Nothing)
        writer.Formatting = Formatting.Indented
        doc.Save(writer)
        writer.Close()
        ' Save the signed XML document to a file specified
        ' using the passed string.
        Dim xmltw As New XmlTextWriter(XmlSigFileName, New UTF8Encoding(False))
        xmlDigitalSignature.WriteTo(xmltw)
        xmltw.Close()
    End Sub
*******************************************************************
    ' Verify the signature of an XML file against an asymetric 
    ' algorithm and return the result.
    Public Function VerifyXmlFile(ByVal OriginalFile As String, ByVal Name As [String], ByVal KeyParameter As RSAParameters) As [Boolean]
        ' Create a new XML document.
        Dim xmlDocument As New XmlDocument
        ' Load the passed XML file into the document. 
        xmlDocument.Load(Name)
        Dim HashElement As XmlElement = CType(xmlDocument.GetElementsByTagName("Hash")(0), XmlElement)
        Dim CurrentHash As String = GetHash(OriginalFile)
        If HashElement.InnerXml <> CurrentHash Then
            Throw New ApplicationException("Signature Failed at Hash level check")
        End If
        Dim signedXml As New SignedXml(xmlDocument)
        Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature")
        ' Load the signature node.
        signedXml.LoadXml(CType(nodeList(0), XmlElement))
        Dim Key As New RSACryptoServiceProvider
        Key.ImportParameters(KeyParameter)
        ' Check the signature and return the result.
        Return signedXml.CheckSignature(Key)
    End Function
*******************************************************************
    Public Function GetHash(ByVal File As String) As String
        Dim SHAHasher As New System.Security.Cryptography.SHA1Managed
        Dim SHAHash() As Byte = SHAHasher.ComputeHash(GetByte(File))
        Dim SHAHashString As String = System.Convert.ToBase64String(SHAHash)
        Return SHAHashString
End Function
Happy Programming
– S
No comments:
Post a Comment