私は政府機関に XML メッセージを送信する作業を行っています (その政府機関の仕様を使用しているため、結果の XML がどのように見える必要があるかを制御することはできません)。開発には C# を使用しています (会社のポリシー)。
C# とインターネット テクノロジに関して私よりもはるかに優れている 2 人が、私より前に XML をレビューし、WCF は XML ドキュメントの署名を生成するために必要なメソッドをサポートしないことを知らせてくれました (これは少し安心しました。私は WCF プロジェクトを開発したことがなく、WCF が成熟した Web テクノロジであることを理解しているため、恐ろしいことです)。
そのため、LINQ to XML と System.Xml の組み合わせを使用してメッセージを生成し、署名を試みました。
以下は、XML の一部を抜粋したサンプルです。
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soap-sec="http://schemas.xmlsoap.org/security/2000-12"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:cns="http://customNamespace1.com"
xmlns:cnt="http://customNamespace2.com"
>
<soapenv:Header>
<ns2:Element1 xmlns:ns2="http://namespace2.element1.com" wsu:Id="id-1">
...
</ns2:Element1>
<ns2:Element2 xmlns:ns2="http://namespace2.element2.com/" wsu:Id="id-2">
...
</ns2:Element2>
<wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<wsu:Timestamp wsu:Id="id-3">
...
</wsu:Timestamp>
<wsse:UsernameToken wsu:Id="id-4">
...
</wsse:UsernameToken>
<wsse:BinarySecurityToken ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-5bf699c7-5336-4695-b395-88d2b984fe54" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
...
</wsse:BinarySecurityToken>
<ds:Signature Id="SIG-6" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="SOAP-ENV cnt soap-sec soapenv sp cns wsdl wsp wsse wsu xs xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#id-1">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="SOAP-ENV cnt soap-sec soapenv sp cns wsdl wsp wsse wsu xs xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>...</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#id-2">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="SOAP-ENV cnt soap-sec soapenv sp cns wsdl wsp wsse wsu xs xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>...</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#id-3">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="SOAP-ENV cnt soap-sec soapenv sp cns wsdl wsp wsse xs xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>...</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#id-4">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="SOAP-ENV cnt soap-sec soapenv sp cns wsdl wsp wsu xs xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>...</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#id-5">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="SOAP-ENV cnt soap-sec sp cns wsdl wsp wsse wsu xs xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>...</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
...
</ds:SignatureValue>
<ds:KeyInfo Id="KI-ABDCFEC7595B7819C213402151542862">
<wsse:SecurityTokenReference wsu:Id="STR-ABDCFEC7595B7819C213402151542863">
<wsse:Reference URI="#SecurityToken-5bf699c7-5336-4695-b395-88d2b984fe54" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body wsu:Id="id-5">
<ns5:bodyelement xmlns:ns4="http://namespace4.com/" xmlns:ns3="http://namespace3.com/" xmlns:ns2="http://bodynamespace2.com/" xmlns:ns5="http://namespace5.com/">
...
</ns5:bodyelement>
</soapenv:Body>
</soapenv:Envelope>
私が試したコードの一部を次に示します (uri フラグメントを機能させるための 3 つの異なる方法)。適切な XML を生成するのに 200 行以上のコードが必要だったので、ここにコードの一部のみを投稿します。現在、署名を試みています。
RSACryptoServiceProvider rsacsp = (RSACryptoServiceProvider)Key;
SignedXml xmlWSig = new SignedXml(myDoc);
xmlWSig.SigningKey = Key;
xmlWSig.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
XmlDsigExcC14NTransform canMethod = (XmlDsigExcC14NTransform)xmlWSig.SignedInfo.CanonicalizationMethodObject;
canMethod.InclusiveNamespacesPrefixList = "SOAP-ENV cns soap-sec soapenv sp cnt wsdl wsp wsse wsu xs xsi";
Uri uri = new Uri("#id-1");
Reference ref1 = new Reference(uri.ToString());
XmlDsigExcC14NTransform transform1 = new XmlDsigExcC14NTransform("SOAP-ENV cns soap-sec soapenv sp cnt wsdl wsp wsse wsu xs xsi");
ref1.AddTransform(transform1);
ref1.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
xmlWSig.AddReference(ref1);
Reference ref2 = new Reference("#id-2");
XmlDsigExcC14NTransform transform2 = new XmlDsigExcC14NTransform("SOAP-ENV cns soap-sec soapenv sp cnt wsdl wsp wsse wsu xs xsi");
ref2.AddTransform(transform2);
ref2.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
xmlWSig.AddReference(ref2);
Reference ref3 = new Reference("");
ref3.Uri = "#id-3";
XmlDsigExcC14NTransform transform3 = new XmlDsigExcC14NTransform("SOAP-ENV cns soap-sec soapenv sp cnt wsdl wsp wsse xs xsi");
ref3.AddTransform(transform3);
ref3.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
xmlWSig.AddReference(ref3);
//repeat things for id-4, and id-5
KeyInfo myKeyInfo = new KeyInfo();
myKeyInfo.AddClause(new RSAKeyValue((RSA)Key));
xmlWSig.KeyInfo = myKeyInfo;
xmlWSig.ComputeSignature();
XmlElement signedXmlElement = xmlWSig.GetXml();
Key は、X509 証明書から取得した秘密鍵です (ドキュメントに署名するための鍵として使用する必要があります)。myDoc は、署名を挿入するために生成した System.Xml XmlDocument です。
方法 #1 System.UriFormatException: 無効な URI: URI の形式を特定できませんでした。
方法 #2 System.Security.Cryptography.CryptograpicException: Malformed reference element が返されます (Uri から # を削除すると、System.UriFormatException: Invalid URI: The URI is empty が返されます)。
方法 3 では、方法 2 と同じエラーが発生します。
署名に Uris を使用することに関するすべてのドキュメントから、Uri Fragment のみを使用することが許可されています (参照されている要素が同じドキュメント内にあると仮定して) が、C# の Uri クラスは Fragments を受け入れ可能な Uri として受け入れないようです。
Reference クラスも、Fragment だけでなく、完全な Uri を必要としているようです。
仕様を使用して、この XML で署名を適切に生成する方法についての提案をお待ちしています。
更新: SignedXml + 参照 + 変換が最適なソリューションのように思えますが、.NET にはこれらのライブラリに大きなギャップがあると考え始めており、署名を生成するためにいくつかの下位レベルのライブラリにドロップダウンする可能性があります。必要。
残念ながら、私はまだどのライブラリが必要か、そして署名が必要なものを見つけるためのアルゴリズムを判断しようとして苦労しています。Exclusive Canonicalization についての私の理解では、InclusiveNamespaces PrefixList にリストされているプレフィックスによって指定された要素にのみ署名していたが、参照の URI は署名が必要なサブドキュメントを指定しているが、指定された要素内の要素は署名されていないということでした。含まれている名前空間のほとんどを使用しないでください。これらのリファレンスが機能する方法を理解していますか?