none
Podepisování XML dokumentů VB.NET

    Dotaz

  • Dobrý den,
    zmigroval jsem jeden server z Win SBS 2003 na Win Server 2003 R2 a né a né přijít na to, proč nefunguje aplikace na podepisování a šifrování XML dokumentů, kterou kdysi napsal kolega ve Visual Basicu .NET 2008.

    Kód vypadá takto :

    Imports System
    Imports System.Security.Cryptography
    Imports System.Security.Cryptography.X509Certificates
    Imports System.Security.Cryptography.Xml
    Imports System.Text
    Imports System.Xml
    Imports System.Xml.XPath
    
    Module Module1
        Dim cAdresar As String
        Dim cSoubor As String
        Dim cCertifikaty As String
    
        Sub Main(ByVal args() As String)
            
            Try
                If args.Length > 0 Then
                    cAdresar = args(0)
                    cSoubor = args(1)
                    cCertifikaty = args(2)
                    Console.WriteLine("Mame parametry ... ")
                    Console.WriteLine(cAdresar)
                Else
                    Console.WriteLine("Nebyly zadany zadne parametry ... pouziju default")
                    cAdresar = "C:\XML\"
                    cCertifikaty = "C:\XML\"
                    cSoubor = "10cz170300g1b20091_15122010113639.xml"
    
                End If
    
    
                Dim rsaKey As New RSACryptoServiceProvider() 'pro SHA 256
                'Dim rsaKey As New SHA256CryptoServiceProvider() 'pro SHA 256 - u WinXP hlaska : Zadaný šifrovací algoritmus není na této platformě podporován. 
    
                ' Create a new XML document.
                Dim xmlDoc As New XmlDocument()
    
                ' Load an XML file into the XmlDocument object.
                xmlDoc.PreserveWhitespace = True
                xmlDoc.Load(cAdresar + cSoubor)
    
                Console.WriteLine(xmlDoc.DocumentElement.Name)
    
                ' Sign the XML document. 
                SignXml(xmlDoc)
    
                ' Save the document.
                xmlDoc.Save(cAdresar + "PODEPSANO\SIG_" + cSoubor)
                xmlDoc.Save("C:\SIG_" + cSoubor)
    
                Dim result As Boolean = VerifyXmlFile(cAdresar + "PODEPSANO\SIG_" + cSoubor)
                If result Then
                    Console.WriteLine("XML podpis OK")
                Else
                    Console.WriteLine("XML podpis KO")
                End If
    
                Dim EcrDoc As New XmlDocument()
                'EcrDoc.Load(cAdresar + "ECROBALKA\ECR_OBALKA.xml")
                EcrDoc.Load(cAdresar + "ECROBALKA\OB_" + cSoubor)
    
                Dim yyy As XmlElement = EcrDoc.DocumentElement
                yyy = yyy.ChildNodes.Item(3)  'tady se dostanu do ./XmlZprava
                yyy = yyy.ChildNodes.Item(0)  'tady se dostanu do ./XmlZprava/Data
                'Console.WriteLine(yyy.ChildNodes.Item(0))
    
    
    
                Dim newBook As XmlNode = EcrDoc.ImportNode(xmlDoc.DocumentElement, True)
    
                yyy.AppendChild(newBook)
    
                EcrDoc.Save(cAdresar + "PODEPSANO\ECR_SIG_" + cSoubor)
                Console.WriteLine("ECR obalka vytvorena...")
            Catch e As Exception
                Console.WriteLine(e.Message)
            End Try
    
            Try
                ' Create an XmlDocument object.
                Console.WriteLine("sifruju soubor...")
                Dim xmlDoc As New XmlDocument()
                ' Load an XML file into the XmlDocument object.
                xmlDoc.PreserveWhitespace = True
                xmlDoc.Load(cAdresar + "PODEPSANO\ECR_SIG_" + cSoubor)
    
    
                Dim cert As X509Certificate2 = Nothing
    
                Dim certificate1 As New X509Certificate2(cCertifikaty + "kom_public.cer")
                cert = certificate1
    
                If cert Is Nothing Then
                    Throw New CryptographicException("The X.509 certificate could not be found.")
                End If
    
    
                ' Encrypt the "creditcard" element.
                Encrypt(xmlDoc, "Data", cert)
    
                ' Save the XML document.
                xmlDoc.Save(cAdresar + "POSLAT\ENC_ECR_SIG_" + cSoubor)
                Console.WriteLine("soubor zasifrovan...")
    
            Catch e As Exception
                Console.WriteLine(e.Message)
            End Try
    
        End Sub 'Main
    
    
        Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementToEncryptName As String, ByVal Cert As X509Certificate2)
            ' Check the arguments.  
            If Doc Is Nothing Then
                Throw New ArgumentNullException("Doc")
            End If
            If ElementToEncryptName Is Nothing Then
                Throw New ArgumentNullException("ElementToEncrypt")
            End If
            If Cert Is Nothing Then
                Throw New ArgumentNullException("Cert")
            End If
            ''''''''''''''''''''''''''''''''''''''''''''''''
            ' Find the specified element in the XmlDocument
            ' object and create a new XmlElemnt object.
            ''''''''''''''''''''''''''''''''''''''''''''''''
            Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)
    
            ' Throw an XmlException if the element was not found.
            If elementToEncrypt Is Nothing Then
                Throw New XmlException("The specified element was not found")
            End If
    
            ''''''''''''''''''''''''''''''''''''''''''''''''
            ' Create a new instance of the EncryptedXml class 
            ' and use it to encrypt the XmlElement with the 
            ' X.509 Certificate.
            ''''''''''''''''''''''''''''''''''''''''''''''''
            Dim eXml As New EncryptedXml()
    
            ' Encrypt the element.
            Dim edElement As EncryptedData = eXml.Encrypt(elementToEncrypt, Cert)
            ''''''''''''''''''''''''''''''''''''''''''''''''
            ' Replace the element from the original XmlDocument
            ' object with the EncryptedData element.
            ''''''''''''''''''''''''''''''''''''''''''''''''
            EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
        End Sub
    
    
        ' Sign an XML file. 
        ' This document cannot be verified unless the verifying 
        ' code has the key with which it was signed.
        Sub SignXml(ByVal Doc As XmlDocument)
            ' Check arguments.
            If Doc Is Nothing Then
                Throw New ArgumentException("Doc")
            End If
    
            Console.WriteLine("Podepisuji soubor....")
    
            ' Create a SignedXml object.
            Dim signedXml As New SignedXml(Doc)
    
            signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
    
            ' Create a reference to be signed.
            Dim reference As New Reference()
            reference.Uri = ""
    
            ' 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)
            ' Compute the signature.
    
            ' Create a new KeyInfo object.
            Dim keyInfo As New KeyInfo()
    
            'Load the X509 certificate.
    
            Dim certificate2 As New X509Certificate2(cCertifikaty + "certifikat.pfx", "heslo")
    
    
            ' Load the certificate into a KeyInfoX509Data object
            ' and add it to the KeyInfo object.
            keyInfo.AddClause(New KeyInfoX509Data(certificate2))
    
            ' Add the KeyInfo object to the SignedXml object.
            signedXml.KeyInfo = keyInfo
    
            signedXml.SigningKey = certificate2.PrivateKey
            Console.WriteLine("pred ComputeSignature")
            signedXml.ComputeSignature()
            Console.WriteLine("po 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))
    
    
            Console.WriteLine("XML soubor podepsan....")
        End Sub
    
        Function GetCertificateBySubject(ByVal CertificateSubject As String) As X509Certificate2
            ' Check the args.
            If Nothing = CertificateSubject Then
                Throw New ArgumentNullException("CertificateSubject")
            End If
    
            ' Load the certificate from the certificate store.
            Dim cert As X509Certificate2 = Nothing
    
            Dim store As New X509Store("My", StoreLocation.CurrentUser)
    
            Try
                ' Open the store.
                store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
    
                ' Get the certs from the store.
                Dim CertCol As X509Certificate2Collection = store.Certificates
    
                ' Find the certificate with the specified subject.
                Dim c As X509Certificate2
                For Each c In CertCol
                    If c.Subject = CertificateSubject Then
                        cert = c
                        Exit For
                    End If
                Next c
    
                ' Throw an exception of the certificate was not found.
                If cert Is Nothing Then
                    Throw New CryptographicException("The certificate could not be found.")
                End If
            Finally
                ' Close the store even if an exception was thrown.
                store.Close()
            End Try
    
            Return cert
    
        End Function
    
        Function VerifyXmlFile(ByVal Name As String) As [Boolean]
            ' 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.Load(Name)
    
            ' 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")
    
            ' Load the signature node.
            signedXml.LoadXml(CType(nodeList(0), XmlElement))
    
    
            ' Check the signature and return the result.
            Return signedXml.CheckSignature()
    
        End Function
    
    End Module

    Problém je ten, že aplikace hlásí tuto chybku :

    Podepisuji soubor....
    pred ComputeSignature
    Pro zadaný podpisový algoritmus nelze vytvořit popis SignatureDescription.


    Údajně je problém s certifikátem, který byl vygenerován na stroji, kde je trochu jinak pojmenované konkrétní CSP (Cryptographic Service Provider) a tím pádem to nejde na jiném OS.
    Když se certifikát vygeneruje na WinXP, tak to bude fungovat jen na WinXP. Když na WinSBS2003, tak jen na něm atd.
    Nicméně toto se mi nezdá moc pravděpodobné a podle mně bude problém někde jinde.

    Řešil jste už někdo něco podobného? Je to ta příčina? Lze to nějak obejít? Nebo je chyba úplně někde jinde?

    Podotýkám, že server je plně zaktualizován včetně všech frameworků a aktualizací zahrnující podporu SHA2 v systému.

    Děkuji mnohokrát
    S pozdravem
    Max Devaine

    26. července 2013 8:31

Odpovědi

Všechny reakce