2017-05-12 19 views
9

文書が改変されていないことを確認したいと思います。私はMSDN上のXMLファイルを検証するために役に立つ例を見つけたデジタルXML署名を確認する方法

<?xml version="1.0" encoding="UTF-8"?><Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" SOAP-ENV:mustUnderstand="1"> 
<wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="CertId-38670273">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</wsse:BinarySecurityToken><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
<ds:SignedInfo> 
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 
<ds:Reference URI="#id-32516734"> 
<ds:Transforms> 
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
</ds:Transforms> 
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
<ds:DigestValue>Rx5L4j8kF5RVYnC+spUCdvhh5N0=</ds:DigestValue> 
</ds:Reference> 
<ds:Reference URI="#id-7716709"> 
<ds:Transforms> 
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
</ds:Transforms> 
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
<ds:DigestValue>fFr2j5DoKTgpEvX1Se7gTC55bWM=</ds:DigestValue> 
</ds:Reference> 
</ds:SignedInfo> 
<ds:SignatureValue> 
jG1BaGgNbbk9JCc3R6JsJKY56p++f0+8RM2aL6TGOXS34NAGv48Sp3iAHEAuUt9+JV6w3VDAcFct 
no3nCEISa0P4dVWTlPQJue3GVTWnnlcXao95tjukh9o8lIU7vZGgYHBUZLU+jgS6ZcaUlNW4KFUl 
AdrPxR5DmJcFyGEtRY2yclqYhnJdnUc+ZBu5eWbRZgbJzR4MgtGsEQcgtftFe2i0CvRbOSe4mt3T 
JQzbGY81ssFCnB44vitgjhVLfPd/08amSa5Xn8KRptbNatp2uq1iGXAifJLVup8T0yS0RzaqhCJg 
CaHRPFVKFN3WaJcqPZex75KBwSZMZaaJDZW7lQ== 
</ds:SignatureValue> 
<ds:KeyInfo Id="KeyId-16708261"> 
<wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-32258670"><wsse:Reference URI="#CertId-38670273" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/></wsse:SecurityTokenReference> 
</ds:KeyInfo> 
</ds:Signature> 
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-32516734"><wsu:Created>2017-03-31T09:04:40.352Z</wsu:Created><wsu:Expires>2017-03-31T09:09:40.352Z</wsu:Expires></wsu:Timestamp></wsse:Security><wsa:MessageID xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" SOAP-ENV:mustUnderstand="0">uuid:12b93a00-15f1-11e7-af6b-f16d80f418ae</wsa:MessageID><wsa:To xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" SOAP-ENV:mustUnderstand="0">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To></SOAP-ENV:Header> 


<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-7716709"> 
... 
</SOAP-ENV:Body></Envelope> 

' Verify the signature of an XML file and return the result. 
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", "http://www.w3.org/2000/09/xmldsig#") 

    ' Load the signature node. 
    signedXml.LoadXml(CType(nodeList(0), XmlElement)) 

    ' Check the signature and return the result. 
    Return signedXml.CheckSignature() 

End Function 
のJava Webサービスから

は、私がデジタル XML署名と、次のSOAP応答を受け取ります

残念ながら、検証では常にfalseが返されます。私はそれがうまくいかない理由を理解するのに苦労します。 Henk HoltermanSimon Mourierからの提案に係る


UPDATE 1

CheckSignature(関数を呼び出して、メッセージ "不正な基準要素" とCryptographicExceptionもたらし
Function VerifyXmlFile(ByVal Name As String) As Boolean 

    ' <SOAP-ENV:Envelope ... > ... </SOAP-ENV:Envelope> 
    Dim xDoc = XDocument.Load(Name) 

    ' <wsse:binarySecurityToken ... > ... </wsse:binarySecurityToken> 
    Dim xBinarySecurityToken = xDoc.Root.Descendants().Skip(2).FirstOrDefault 

    ' <SOAP-ENV:Body ... > ... </SOAP-ENV:Body> 
    Dim xBody = xDoc.Root.Elements().Skip(1).FirstOrDefault 
    Dim signedXml = New SignedXml(ToXmlElement(xBody)) 

    Dim xmlDocument As New XmlDocument() 
    xmlDocument.PreserveWhitespace = True 
    xmlDocument.Load(Name) 

    Dim nodeList = xmlDocument.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#") 
    signedXml.LoadXml(CType(nodeList(0), XmlElement)) 

    Dim byteCert = Encoding.UTF8.GetBytes(xBinarySecurityToken.Value) 
    Dim cert = New X509Certificates.X509Certificate2(byteCert) 

    Return signedXml.CheckSignature(cert, True) 

End Function 

Public Shared Function ToXmlElement(xElement As XElement) As XmlElement 
    Dim xmlDoc = New XmlDocument() With {.PreserveWhitespace = True} 
    xmlDoc.Load(xElement.CreateReader()) 
    Return xmlDoc.DocumentElement 
End Function 

@SimonMourier@CarlosLopez-MSFT

Dog Ears

Public Class SignedXmlWithId 
Inherits SignedXml 

Public Sub New(xml As XmlDocument) 
    MyBase.New(xml) 
End Sub 

Public Sub New(xmlElement As XmlElement) 
    MyBase.New(xmlElement) 
End Sub 

Public Overrides Function GetIdElement(doc As XmlDocument, id As String) As XmlElement 
    ' check to see if it's a standard ID reference 
    Dim idElem As XmlElement = MyBase.GetIdElement(doc, id) 

    If idElem Is Nothing Then 
     Dim nsManager As New XmlNamespaceManager(doc.NameTable) 
     nsManager.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd") 

     idElem = TryCast(doc.SelectSingleNode((Convert.ToString("//*[@wsu:Id=""") & id) + """]", nsManager), XmlElement) 
    End If 

    Return idElem 
End Function 

End Class 

クレジットから盗まれたヘルパークラス@SimonMourierからの提案にとlax1089

Private Function VerifyXmlfile(Name As String) As Boolean 
    CryptoConfig.AddAlgorithm(GetType(MyXmlDsigC14NTransform), "http://www.w3.org/TR/2001/REC-xml-c14n-20010315") 

    Dim xmlDocument As New XmlDocument() 
    xmlDocument.PreserveWhitespace = True 
    xmlDocument.Load(Name) 
    MyXmlDsigC14NTransform.document = xmlDocument 

    Dim soapBody As XmlElement = xmlDocument.GetElementsByTagName("SOAP-ENV:Body")(0) 
    Dim securityToken = xmlDocument.GetElementsByTagName("SOAP-ENV:Header")(0).FirstChild.NextSibling.FirstChild.NextSibling.InnerText 

    Dim signedXml = New SignedXmlWithId(soapBody) 

    Dim nodeList = xmlDocument.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#") 
    signedXml.LoadXml(CType(nodeList(0), XmlElement)) 

    Dim byteCert = Convert.FromBase64String(securityToken) 
    Dim cert = New X509Certificates.X509Certificate2(byteCert) 

    Return signedXml.CheckSignature(cert, True) 

End Function 

@に従って


UPDATE 2とSOLUTION

+1

'Dim signedXml As New SignedXml(xmlDocument)'部分は、署名された部分としてドキュメント全体を選択します。代わりにSOAP-ENV:Bodyを選択する必要があると思います。 id-7716709に注意してください。しかし、あなたは確かにドキュメントが必要です。タイムスタンプも署名されているようだが、これはオプションかどうかわからない。 –

+1

これは、デフォルトでは、SignedXmlは公開キーを認識しないためです(wsse:BinarySecurityToken(base64でエンコードされたX509証明書)のみをデコードすることはできません。ただし、wsse:BinarySecurityTokenの内容をbyte []としてデコードしたX509Certificateを作成し、それをCheckSignatureに渡すと、それが動作するはずです。しかし、それはまだ私のために動作しません。私は必要なルート証明書を持っていない可能性があります(スイスの権威から来ています)... –

+0

[link] https://msdn.microsoft.com/en-us/library/ms229950(v = vs.110).aspxここで、鍵がどのように生成されているかを知ることができます。アルゴリズムの中で、関数 'signedXml.CheckSignature(Key) 'の引数としてキーがないことがあなたの問題と関係しているかどうかを確認することができます。 – mago

答えて

1

は、実はこれが知られており、文書化の問題である:

.NET 3.5と.NET 4.0の間に正規化の実装は が変更されました。

これがすべてのXML署名で機能するかどうかはわかりませんが、私が行ったテストからはうまくいきます。

プロジェクトにクラスを変換following C14Nを追加します。

public class MyXmlDsigC14NTransform: XmlDsigC14NTransform { 
    static XmlDocument _document; 
    public static XmlDocument document { 
    set { 
     _document = value; 
    } 
    } 

    public MyXmlDsigC14NTransform() {} 

    public override Object GetOutput() { 
    return base.GetOutput(); 
    } 

    public override void LoadInnerXml(XmlNodeList nodeList) { 
    base.LoadInnerXml(nodeList); 
    } 

    protected override XmlNodeList GetInnerXml() { 
    XmlNodeList nodeList = base.GetInnerXml(); 
    return nodeList; 
    } 

    public XmlElement GetXml() { 
    return base.GetXml(); 
    } 

    public override void LoadInput(Object obj) { 
    int n; 
    bool fDefaultNS = true; 

    XmlElement element = ((XmlDocument) obj).DocumentElement; 

    if (element.Name.Contains("SignedInfo")) { 
     XmlNodeList DigestValue = element.GetElementsByTagName("DigestValue", element.NamespaceURI); 
     string strHash = DigestValue[0].InnerText; 
     XmlNodeList nodeList = _document.GetElementsByTagName(element.Name); 

     for (n = 0; n < nodeList.Count; n++) { 
     XmlNodeList DigestValue2 = ((XmlElement) nodeList[n]).GetElementsByTagName("DigestValue", ((XmlElement) nodeList[n]).NamespaceURI); 
     string strHash2 = DigestValue2[0].InnerText; 
     if (strHash == strHash2) break; 
     } 

     XmlNode node = nodeList[n]; 

     while (node.ParentNode != null) { 
     XmlAttributeCollection attrColl = node.ParentNode.Attributes; 
     if (attrColl != null) { 
      for (n = 0; n < attrColl.Count; n++) { 
      XmlAttribute attr = attrColl[n]; 
      if (attr.Prefix == "xmlns") { 
       element.SetAttribute(attr.Name, attr.Value); 
      } else if (attr.Name == "xmlns") { 
       if (fDefaultNS) { 
       element.SetAttribute(attr.Name, attr.Value); 
       fDefaultNS = false; 
       } 
      } 
      } 
     } 

     node = node.ParentNode; 
     } 
    } 

    base.LoadInput(obj); 
    } 
} 

そして、以下に示すようCryptoConfig.AddAlgorithmメソッドを使ってクラスを登録します。これは、あなたが適切に検証できるようにする必要があり

CryptoConfig.AddAlgorithm(typeof(MyXmlDsigC14NTransform), "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); 

var message = new XmlDocument(); 
message.PreserveWhitespace = true; 
message.Load("XmlSig.xml"); 

MyXmlDsigC14NTransform.document = message; // The transform class needs the xml document 

// Validate signature as normal. 

XML署名を作成し、問題を解決します。

関連する問題