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

How do I properly sign a SOAP message with SHA2 in C#?

我使用的第 3 方服务满足以下要求

Transactions dealing with personal information and other sensitive data use transport layer security protection. The web service message will be transported over https (HTTP over SSL) and must adhere to Web Service (WS)-Security v1.1 standard. The WS-Security section of the service message must:

  • Be signed with x.509 certificate using a 2048 bit key size
  • Use SHA2 with RSA algorithm for encryption
  • Use C14 canonicalization.

我成功地使用以下代码对我的消息进行了签名

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 签名的。我正在尝试正确签署我的消息,但我在网上找到的示例让您生成 soap 消息,然后使用 XML 解析和添加新节点手动修改它。我不理解这些例子,我正在尝试找出一种方法来告诉服务为我做这件事。我有一个来自下面第 3 方的请求签名的示例。我在客户端或绑定 class 中看不到任何允许我更改签名算法等内容的内容。我该怎么做?

<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>

得到它工作这里是最终的解决方案

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();
    }
}