关于c#:如何在自定义绑定中使用RSA-SHA512作为defaultAlgorithmSuite中的签名算法?

How do I use RSA-SHA512 as signing algorithm in defaultAlgorithmSuite in custom bindings?

我正在根据以下内容对XML进行签名:签名算法:http://www.w3.org/2001/04/xmldsig more rsa-sha512摘要算法:http://www.w3.org/2001/04/xmlenc sha512规范化算法:http://www.w3.org/2001/10/xml-exc-c14n#

但我在WCF中找不到对Sha512的支持。有解决办法吗?

以下是我的代码:

1
2
3
4
5
6
7
8
9
<customBinding>
    <binding name="McBinding">
         <textMessageEncoding messageVersion="Soap11" />
        <security authenticationMode="MutualCertificate" includeTimestamp="false" defaultAlgorithmSuite="??"
            messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
            <secureConversationBootstrap />
        </security>
        <httpsTransport />
    </binding>

我遇到的问题是不支持RSA-SHA512签名算法。它可以通过使用自定义签名算法来实现。然后将其添加到自定义绑定中的默认签名算法中。

1
 public class MyCustomAlgorithmSuite : SecurityAlgorithmSuite { }

还为此创建签名为:

1
2
public class RsaPkCs1Sha512SignatureDescription : SignatureDescription
{}

然后将其添加到:

1
2
CryptoConfig.AddAlgorithm(typeof(RsaPkCs1Sha512SignatureDescription),
           "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512");

但是,我们在签署二进制安全令牌时遇到了一个问题。可通过添加以下内容进行签名:

1
assymetricKey.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());

但是,这将创建一个新的签名二进制安全令牌,您将得到两个BST。解决此问题的方法是:

1
2
            assymetricKey.InitiatorTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.Never};
        assymetricKey.RecipientTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.Never};

这会使您的signedInfo混乱,从而丢失对bst的引用,我们被卡住了。

总之,我们最终没有使用WCF功能,而是使用了:

1
SignedXML class.

以下链接可供参考:https://gist.github.com/luizvaz/43ccbd85b16b6802218b50b6d34c26de

另外,这里要注意的是,如果您正在从证书实现签名算法RSA-SHA512,那么您将需要使用扩展方法(确保使用.NET 4.6.2或更高版本)。对于旧版本:

signedXML使用sha256计算签名

1
signedXml.SigningKey = RSACertificateExtensions.GetRSAPrivateKey(cert);

另外,如果您将前缀作为ds添加到签名中,则需要从SignedInfo中删除引用,重新计算签名并将其添加回去。

生成数字签名,但使用特定的命名空间前缀("ds:")

我希望这有助于有类似的问题。