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


Partial Public Class TestXEncFF
    Inherits System.Web.UI.Page

    Private Function DecryptXml(ByVal EncryptedXml As XmlDocument, ByVal cert As X509Certificate2) As XmlDocument
        'W3C Xml Encryption spec. does not include KeyInfo element in the EncryptedKey element,
        'but .Net need it (is KeyName) in order to decrypt key with asymetric algorithm

        Dim doc As XmlDocument = EncryptedXml.Clone
        For Each xn As XmlNode In doc.GetElementsByTagName("xenc:EncryptedKey")
            Dim ki As XmlNode = xn.SelectSingleNode("KeyInfo")
            If ki Is Nothing Then
                ki = doc.CreateElement("KeyInfo")
                Dim a As System.Xml.XmlAttribute = doc.CreateAttribute("xmlns")
                a.InnerText = "http://www.w3.org/2000/09/xmldsig#"
                ki.Attributes.Append(a)


                Dim kn As XmlElement = doc.CreateElement("KeyName")
                kn.InnerText = "rsaKey"

                ki.AppendChild(kn)
                xn.AppendChild(ki)
            End If
        Next

        Dim xdoc As New XmlDocument 'Create a new XML and decrypt its data
        xdoc.LoadXml(doc.OuterXml)

        ' Create a new EncryptedXml object.
        Dim exml As New EncryptedXml(xdoc)

        ' Add a key-name mapping.
        ' This method can only decrypt documents
        ' that present the specified key name.
        exml.AddKeyNameMapping("rsaKey", cert.PrivateKey)
        ' Decrypt the element.
        exml.DecryptDocument()

        Return xdoc
    End Function

    Private Function GetCertificate(ByVal thumbprint As String) As X509Certificates.X509Certificate2
        ' pick a certificate from the store

        ' TODO: This is a sample code so it picks up first certificate from a store. 
        ' Change this to load the right certificate


        Dim cert As X509Certificates.X509Certificate2 = Nothing
        Dim store As New System.Security.Cryptography.X509Certificates.X509Store(X509Certificates.StoreName.My, X509Certificates.StoreLocation.CurrentUser)
        store.Open(X509Certificates.OpenFlags.ReadOnly)

        If store.Certificates.Count > 0 Then
            If store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, False).Count > 0 Then
                cert = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, False)(0)
            End If
        End If

        store.Close()

        Return cert
    End Function

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Try
            'Load some XML document (you can also use serialized XML document)
            Dim xml As New System.Xml.XmlDocument
            xml.Load(Server.MapPath("~\PaymentInfo.xml"))

            Me.lblXml.Text = Server.HtmlEncode(xml.OuterXml)

            'Sote XML in hidden field
            hiddenXml.Value = xml.OuterXml
        Catch ex As Exception
            lblXml.Text = ex.ToString()
        End Try
    End Sub

    Protected Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
            Dim encxml As New XmlDocument
            encxml.LoadXml(hiddenEncryptedXml.Value)

            Me.lblEncryptedXml.Text = Server.HtmlEncode(encxml.OuterXml)

            Dim base64cert As String = encxml.GetElementsByTagName("ds:X509Certificate")(0).InnerText
            Dim certKeyInfo As New X509Certificate2(Convert.FromBase64String(base64cert))
            Dim cert As X509Certificate2 = GetCertificate(certKeyInfo.Thumbprint)

            If cert Is Nothing Then
                Throw New NullReferenceException("cert is nothing")
            End If

            Dim doc As XmlDocument = DecryptXml(encxml, cert)
            Me.lblDecryptedXml.Text = Server.HtmlEncode(doc.OuterXml)
        Catch ex As Exception
            lblDecryptedXml.Text = ex.ToString()
        End Try
    End Sub

End Class