Подписать XML-документ сертификатом

#xml #vb.net #x509certificate #sign

#xml #vb.net #x509certificate #подписать

Вопрос:

Мне нужно подписать этот XML-файл ( https://www.dropbox.com/s/qfkfvkc83kt72mb/20381235051-01-FF11-04.xml ) с сертификатом x509 v3, но подпись должна быть прикреплена на этом узле:

Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent (строки 19-20)

Я нашел код для подписи XML-файла, но он прикреплен в конце документа, как мне поступить?

Вот мой код:

 Dim f_adresse As String = System.AppDomain.CurrentDomain.BaseDirectory
Dim f_temp As String = f_adresse amp; "TEMP"
Dim f_fichier As String = "20381235051-01-FF11-04.xml"
Dim f_certificat As String = f_adresse amp; "aG9CcVpHVndCWTd3WlVOVw==.p12"
Dim f_pwd As String = "xxxxxxxxxxxxxxxx"

Dim xmlFile As String = f_temp amp; f_fichier

Dim MonCertificat As X509Certificate2 = New X509Certificate2(f_certificat, f_pwd)

Dim xmlDoc As XmlDocument = New XmlDocument()
xmlDoc.PreserveWhitespace = True
xmlDoc.Load(xmlFile)

Dim signedXml As SignedXml = New SignedXml(xmlDoc)

Dim KeyInfo As KeyInfo = New KeyInfo()
Dim Reference As Reference = New Reference()
Reference.Uri = ""

Reference.AddTransform(New XmlDsigEnvelopedSignatureTransform())

signedXml.AddReference(Reference)

Dim X509Chain As X509Chain = New X509Chain()
X509Chain.Build(MonCertificat)

Dim local_element As X509ChainElement = X509Chain.ChainElements(0)
Dim x509Data As KeyInfoX509Data = New KeyInfoX509Data(local_element.Certificate)
Dim subjectName As String = local_element.Certificate.Subject

x509Data.AddSubjectName(subjectName)
KeyInfo.AddClause(x509Data)

signedXml.KeyInfo = KeyInfo
signedXml.ComputeSignature()

Dim signature As XmlElement = signedXml.GetXml()

For Each node As XmlNode In signature.SelectNodes("descendant-or-self::*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#']")
    node.Prefix = "ds"
    If node.LocalName = "Signature" Then
        Dim newAttribute As XmlAttribute = xmlDoc.CreateAttribute("Id")
        newAttribute.Value = "SignatureSP"
        node.Attributes.Append(newAttribute)
     End If
Next node


xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(signature, True))
xmlDoc.Save(xmlFile)
  

Спасибо

Редактировать: в конце моего кода, но не работает:

 For Each node As XmlNode In signature.SelectNodes("descendant-or-self::*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#']")
    node.Prefix = "ds"
    If node.LocalName = "Signature" Then
        Dim newAttribute As XmlAttribute = xmlDoc.CreateAttribute("Id")
        newAttribute.Value = "SignatureSP"
        node.Attributes.Append(newAttribute)
     End If
Next node

Dim signNode As XmlNode = xmlDoc.SelectSingleNode("/tns:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent")
If Not signNode Is Nothing Then
    signNode.AppendChild(xmlDoc.ImportNode(signature, True))
End If

xmlDoc.Save(xmlFile)
  

Ответ №1:

Получите этот узел, затем добавьте. Если вам нужно загрузить пространства имен:

 Dim nsMgr As XmlNamespaceManager
nsMgr = New XmlNamespaceManager(xmlDoc.NameTable)
nsMgr.AddNamespace("sac", "urn:sunat:names:specification:ubl:peru:schema:xsd:SunatAggregateComponents-1")
nsMgr.AddNamespace("ccts", "urn:un:unece:uncefact:documentation:2")
nsMgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
nsMgr.AddNamespace("tns", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2")
nsMgr.AddNamespace("cac", "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2")
nsMgr.AddNamespace("udt", "urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2")
nsMgr.AddNamespace("ext", "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2")
nsMgr.AddNamespace("qdt", "urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2")
nsMgr.AddNamespace("cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2")
nsMgr.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#")

Dim signNodes = mlDoc.SelectNodes
    ("/tns:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent", nsMgr)

If signNodes.Count > 0 Then
 signNodes(0).AppendChild(xmlDoc.ImportNode(signature, True))
End If
  

Комментарии:

1. должен ли я заменить цикл for этим кодом? как найти также значение xpath? я пробовал /Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent, но это не работает. Я также должен добавить префикс «ds» к узлу подписи и к каждому дочернему узлу

2. Liquid XML дает мне это для xpath для коллекции, поэтому просто получите первый — {/tns:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent}

3. Я попробовал метод, который вы предложили мне попробовать, но он не работает, в нем говорится, что запрос имеет префикс. Я не знаю, может ли это помочь или нет, узел ext: UBLExtensions имеет 2 дочерних узла ext: UBLExtension

4. это не имеет смысла, метод SelectNodes возвращает элемент XmlNodeList, методы appendChild и firstChild недоступны. В вашем коде есть одна вещь, которую я неправильно понимаю: как я должен обновить свою переменную xmlDoc?

5. Я думал о другом объекте.