1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
| Public Shared Sub SignXmlFile(ByVal FileName As String, ByVal SignedFileName As String, ByVal cert As X509Certificate2)
Dim Key As RSACryptoServiceProvider
Dim doc As XmlDocument
Dim signedXml As CustomSignedXml
Dim ref As Reference
Dim docNav As XPathNavigator
Dim nSpMgr As XmlNamespaceManager
Dim bodyNav As XPathNavigator
Dim c_GUID As String = Guid.NewGuid().ToString().Replace("-", "").ToUpper
Dim bodyID As String = Nothing
Dim signatureID As String = "SIG-" & c_GUID & "1"
Dim keyInfoID As String = "KI-" & c_GUID & "2"
Dim securityTokenReferenceID As String = "STR-" & c_GUID & "3"
If Not cert.HasPrivateKey Then
Return
End If
'Recuperation de la clé privée
Key = GetCertificateKey(cert)
doc = New XmlDocument
'Ignorer les espaces
doc.PreserveWhitespace = True
'Charger le fichier dans l'objet
doc.Load(FileName)
'Creation de l'objet Signature
signedXml = New CustomSignedXml(doc)
'Objet pour parcourir le document
docNav = doc.CreateNavigator()
'Ajout des différents namespaces
nSpMgr = New XmlNamespaceManager(doc.NameTable)
nSpMgr.AddNamespace("soapenv", CustomSignedXml.xmlSoapEnvelopeUrl)
nSpMgr.AddNamespace("wsu", CustomSignedXml.xmlOasisWSSSecurityUtilUrl)
nSpMgr.AddNamespace("wsse", CustomSignedXml.xmlOasisWSSSecurityExtUrl)
nSpMgr.AddNamespace("ser", "http://service.lockataire.swl.be/")
'Se positionner sur l'élément body afin de lui ajouter un ID
bodyNav = docNav.SelectSingleNode("/soapenv:Envelope/soapenv:Body", nSpMgr)
If bodyNav.HasAttributes Then
bodyID = bodyNav.GetAttribute("id", CustomSignedXml.xmlOasisWSSSecurityUtilUrl)
End If
If String.IsNullOrEmpty(bodyID) Then
Dim bWasNull As Boolean = (bodyID Is Nothing)
bodyID = "id-" & c_GUID & "4"
If bWasNull Then
bodyNav.CreateAttribute("wsu", "id", CustomSignedXml.xmlOasisWSSSecurityUtilUrl, bodyID)
Else
If bodyNav.MoveToAttribute("id", CustomSignedXml.xmlOasisWSSSecurityUtilUrl) Then bodyNav.SetValue(bodyID)
End If
End If
'Ajout de la clé
signedXml.SigningKey = GetCertificateKey(cert) 'cert.PrivateKey
'ID de la clé SIG-xxxxx
signedXml.Signature.Id = signatureID
signedXml.SignedInfo.CanonicalizationMethod = signedXml.XmlDsigExcC14NTransformUrl '"http://www.w3.org/2001/10/xml-exc-c14n#"
Dim canMethod As XmlDsigExcC14NTransform = CType(signedXml.SignedInfo.CanonicalizationMethodObject, XmlDsigExcC14NTransform)
canMethod.InclusiveNamespacesPrefixList = "ser soapenv"
Dim reference As Reference = New Reference()
reference.Uri = "#" & bodyID
Dim c14n As New XmlDsigExcC14NTransform()
c14n.InclusiveNamespacesPrefixList = "ser"
c14n.Algorithm = signedXml.XmlDsigExcC14NTransformUrl
reference.AddTransform(c14n)
reference.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1"
'Ajout de la référence à l'objet SignXML
signedXml.AddReference(reference)
'Création du KeyIdentifier
Dim KeyInfoNode As New KeyInfoNode()
Dim securityRef As XmlElement = doc.CreateElement("wsse", "SecurityTokenReference", "")
securityRef.SetAttribute("Id", "", securityTokenReferenceID)
Dim keyIdentifier As XmlElement = doc.CreateElement("wsse:KeyIdentifier", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")
keyIdentifier.InnerText = Convert.ToBase64String(cert.RawData)
Dim ValueType As XmlAttribute = doc.CreateAttribute("ValueType")
ValueType.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
keyIdentifier.Attributes.Append(ValueType)
Dim encodingType As XmlAttribute = doc.CreateAttribute("EncodingType")
encodingType.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
keyIdentifier.Attributes.Append(encodingType)
securityRef.AppendChild(keyIdentifier)
KeyInfoNode.Value = securityRef
Dim keyInfo As New KeyInfo()
keyInfo.Id = keyInfoID
keyInfo.AddClause(KeyInfoNode)
signedXml.KeyInfo = keyInfo
signedXml.SignedInfo.SignatureMethod = signedXml.XmlDsigRSASHA1Url '"http://www.w3.org/2000/09/xmldsig#rsa-sha1"
signedXml.ComputeSignature()
Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
SetPrefix("ds", xmlDigitalSignature)
signedXml.LoadXml(xmlDigitalSignature)
signedXml.SignedInfo.References.Clear()
signedXml.ComputeSignature()
Dim recomputedSignature As String = Convert.ToBase64String(signedXml.SignatureValue)
ReplaceSignature(xmlDigitalSignature, recomputedSignature)
If signedXml.CheckSignature(cert, True) = True Then
'La signature est OK
End If
doc.SelectSingleNode("soapenv:Envelope/soapenv:Header/wsse:Security", nSpMgr).AppendChild(doc.ImportNode(xmlDigitalSignature, True))
doc.Save(SignedFileName)
If VerifyXmlFile(SignedFileName, cert) = False Then
'REFUSE : La signature n'est plus valide
End If
End Sub
Private Shared Sub ReplaceSignature(ByVal signature As XmlElement, ByVal newValue As String)
If signature Is Nothing Then Throw New ArgumentNullException(NameOf(signature))
If signature.OwnerDocument Is Nothing Then Throw New ArgumentException("No owner document", NameOf(signature))
Dim nsm As XmlNamespaceManager = New XmlNamespaceManager(signature.OwnerDocument.NameTable)
nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl)
Dim signatureValue As XmlNode = signature.SelectSingleNode("ds:SignatureValue", nsm)
If signatureValue Is Nothing Then Throw New Exception("Signature does not contain 'ds:SignatureValue'")
signatureValue.InnerXml = newValue
End Sub
Private Shared Sub SetPrefix(ByVal prefix As String, ByVal node As XmlNode)
Select Case node.Name
Case "InclusiveNamespaces"
node.Prefix = "ec"
Case "wsse:SecurityTokenReference", "wsse:KeyIdentifier"
'node.Prefix = "wsse"
Case "Id"
node.Prefix = "wsu"
Case Else
node.Prefix = prefix
End Select
For Each n As XmlNode In node.ChildNodes
SetPrefix(prefix, n)
Next
End Sub
Public Shared Function VerifyXmlFile(ByVal Name As String, ByVal cert As X509Certificate2) As Boolean
Dim xmlDocument As XmlDocument = New XmlDocument()
xmlDocument.PreserveWhitespace = True
xmlDocument.Load(Name)
Dim signedXml As CustomSignedXml = New CustomSignedXml(xmlDocument)
Dim signatureElement As XmlElement = Nothing
Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("ds:Signature")
If (nodeList Is Nothing) OrElse (nodeList.Count = 0) Then
nodeList = xmlDocument.GetElementsByTagName("ds:Signature", signedXml.XmlDsigNamespaceUrl)
End If
If (nodeList IsNot Nothing) AndAlso (nodeList.Count > 0) Then
signatureElement = CType(nodeList(0), XmlElement)
Else
Return False
End If
signedXml.LoadXml(signatureElement)
Return signedXml.CheckSignature(cert, True)
End Function |
Partager