如何在 C# 中使用 SHA2 正确签署 SOAP 消息?

Posted

技术标签:

【中文标题】如何在 C# 中使用 SHA2 正确签署 SOAP 消息?【英文标题】:How do I properly sign a SOAP message with SHA2 in C#? 【发布时间】:2021-03-23 01:39:06 【问题描述】:

我正在使用的第三方服务有以下要求

处理个人信息和其他敏感信息的交易 数据使用传输层安全保护。网络服务消息 将通过 https(HTTP over SSL)传输,并且必须遵守 Web 服务 (WS)-Security v1.1 标准。 WS-Security 部分 服务信息必须:

使用 x.509 证书使用 2048 位密钥大小进行签名 使用 SHA2 和 RSA 算法进行加密 使用 C14 规范化。

我设法用以下代码签署了我的消息

someServiceRef.widjetClient client = null;

try

    X509Certificate2 signingCert = GetSigningCert();
    var bindings = new BasicHttpsBinding();
    bindings.Security.Mode = BasicHttpsSecurityMode.TransportWithMessageCredential;
    bindings.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;

    client = new someServiceRef.widjetClient(
        bindings,
        new EndpointAddress(@"<URL OF SERVICE>"));

    client.ClientCredentials.ClientCertificate.Certificate = signingCert;
    client.ClientCredentials.ServiceCertificate.DefaultCertificate = signingCert;

    client.Open();

    var request = BuildRequest();

    var response = client.SayHello(request);

    Console.WriteLine(response);

finally

    if (client != null)
    
        if (client.State == System.ServiceModel.CommunicationState.Faulted)
            client.Abort();
        else
            client.Close();
    

问题是我的消息是用 sha1 而不是 sha2 签名的。我正在尝试正确签署我的消息,但我在网上找到的示例让您生成肥皂消息,然后使用 XML 解析手动修改它并添加新节点。我不明白这些例子,我正试图找出一种方法来告诉服务为我做这件事。我有一个来自下面第 3 方的请求签名的示例。我在客户端或绑定类中看不到任何允许我更改签名算法等内容的内容。我该怎么做呢?

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 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="XWSSGID-12324774331131695995061">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</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-sha2" />
                    <ds:Reference URI="#XWSSGID-1232477437326-1352495766">
                        <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha2" />
                        <ds:DigestValue>XXXXXXXXXXXXXXXXXXXXXX</ds:DigestValue>
                    </ds:Reference>
                    <ds:Reference URI="#XWSSGID-1232477437326-823787906">
                        <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha2" />
                        <ds:DigestValue>XXXXXXXXXXXXXXXXXXXXX</ds:DigestValue>
                    </ds:Reference>
                </ds:SignedInfo>
                <ds:SignatureValue>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</ds:SignatureValue>
                <ds:KeyInfo>
                    <wsse:SecurityTokenReference xmlns:wsse="http://www.w3.org/2000/09/xmldsig#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsse:Id="XWSSGID-1232477437311698965010">
                        <wsse:Reference URI="#XWSSGID-12324774331131695995061" />
                        <ds:X509Data>
                            <ds:X509IssuerName>XXXXXXXXXXXXXXXXXXXXXXXXX</ds:X509IssuerName>
                            <ds:X509SerialNumber>XXXXXXXXXXXXXXXXXXX</ds:X509SerialNumber>
                        </ds:X509Data>
                    </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="XWSSGID-1232477437326-823787906">
                <wsu:Created>2009-01-20T18:50:37.233Z</wsu:Created>
                <wsu:Expires>2009-01-20T18:50:42.233Z</wsu:Expires>
            </wsu:Timestamp>
        </wsse:Security>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body xmlns:SOAP-ENV="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="XWSSGID-1232477437326-1352495766">
        BODY OF MESSAGE GOES HERE
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

【问题讨论】:

Sha2 是 256 SHA。所以使用以下内容:docs.microsoft.com/en-us/dotnet/api/… 这不能回答我的问题。在创建服务或绑定时,我会在哪里做这样的事情?您发布的示例只是计算文件的哈希 sha 的默认版本(sh1 或 sha 256)取决于 Net 的版本。请参阅以下内容:docs.microsoft.com/en-us/dotnet/framework/migration-guide/… 这可能对你有帮助:social.msdn.microsoft.com/Forums/vstudio/en-US/… @TheobaldDu 是的,这是其中的一部分。 2天前我就想通了。我会发布解决方案 【参考方案1】:

在这里工作是最终的解决方案

someServiceRef.widjetClient client = null;

try

    X509Certificate2 signingCert = GetSigningCert();
    var bindings = new BasicHttpsBinding();
    bindings.Security.Mode = BasicHttpsSecurityMode.TransportWithMessageCredential;
    bindings.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
    bindings.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256

    var elements = bindings.CreateBindingElements();
    elements.Find<SecurityBindingElement>().EnableUnsecuredResponse = true;
    var customBindings = new CustomBinding(elements);

    client = new someServiceRef.widjetClient(
        customBindings,
        new EndpointAddress(@"<URL OF SERVICE>"));

    client.ClientCredentials.ClientCertificate.Certificate = signingCert;
    client.ClientCredentials.ServiceCertificate.DefaultCertificate = signingCert;

    client.Open();

    var request = BuildRequest();

    var response = client.SayHello(request);

    Console.WriteLine(response);

finally

    if (client != null)
    
        if (client.State == System.ServiceModel.CommunicationState.Faulted)
            client.Abort();
        else
            client.Close();
    

【讨论】:

以上是关于如何在 C# 中使用 SHA2 正确签署 SOAP 消息?的主要内容,如果未能解决你的问题,请参考以下文章

签署 JAX-WS SOAP 请求

如何在 C# 中更改soap xml Web 服务?

在 C# 中,如何使用大量精美的标记将 POCO 序列化为 XML?

C# SOAP Webservice 方法返回 null

如何使用 C# 发送/接收 SOAP 请求和响应?

使用来自 etoken c# 的不可导出私钥签署 xml 请求