【问题标题】:SHA256 signing stops working in .NET 4.5SHA256 签名在 .NET 4.5 中停止工作
【发布时间】:2013-11-06 09:49:15
【问题描述】:

我们有一段代码创建了一个 SigningCredentials 对象,用于使用 SHA256 算法对 xml 文档进行签名。它与 .NET 3.5 完美配合。但是,当我们将代码库升级到 .NET 4.5 时,它就会停止工作。相同的代码,相同的证书!我花了几个小时在互联网上调试和搜索,但没有任何运气。

谁能告诉我这里的问题是什么?提前谢谢你。

创建 SigningCredentials 的代码:

public SigningCredentials CreateSigningCredentials(X509Certificate2 cert)
{
    var ski = new SecurityKeyIdentifier(new X509RawDataKeyIdentifierClause(cert));
    return new SigningCredentials(new X509AsymmetricSecurityKey(cert), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256", ski);
}

例外:

[CryptographicException: Invalid algorithm specified.
]
   System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) +41
   System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature) +0
   System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash) +118
   System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash) +334
   System.Security.Cryptography.RSAPKCS1SignatureFormatter.CreateSignature(Byte[] rgbHash) +321
   System.IdentityModel.SignedXml.ComputeSignature(HashAlgorithm hash, AsymmetricSignatureFormatter formatter, String signatureMethod) +323
   System.IdentityModel.SignedXml.ComputeSignature(SecurityKey signingKey) +690
   System.IdentityModel.EnvelopedSignatureWriter.ComputeSignature() +338
   System.IdentityModel.EnvelopedSignatureWriter.OnEndRootElement() +278
   System.IdentityModel.Metadata.MetadataSerializer.WriteEntityDescriptor(XmlWriter inputWriter, EntityDescriptor entityDescriptor) +1109

【问题讨论】:

    标签: .net certificate wif signing sha256


    【解决方案1】:

    与 XmlDsig 有同样的问题(尝试使用 RSA-SHA256 算法对 xml 文档进行封装签名)。 首先我遇到了异常

    System.Security.Cryptography.CryptographicException: 无法为签名算法创建 SignatureDescription 提供。

    然后我发现提到了RSAPKCS1SHA256SignatureDescription - RSA-SHA256 签名的签名描述实现。
    在这里完整实现:​​
    http://clrsecurity.codeplex.com/SourceControl/changeset/view/47833#269110
    或在这里:https://gist.github.com/sneal/f35de432115b840c4c1f

    您必须为每个 appdomain 手动调用一次:

    CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
    

    在那之后我得到了一个新的例外:

    System.Security.Cryptography.CryptographicException:算法无效 指定。

    这让我想到了你的问题。阅读建议的article 后,我使用Microsoft Enhanced RSA and AES Cryptographic Provider 制作了一个新的密钥和证书(使用OpenSSL)。
    令我惊讶的是,这个新证书让我能够成功地进行签名。

    经过更多调查,我在这里找到了 Andrew 的有趣答案https://stackoverflow.com/a/17285774/328785,他使用RSACryptoServiceProviderSignedXml 课程准备 SecretKey。 特别是这部分(我的解释):

    var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
    var certificates =  store.Certificates.Find(X509FindType.FindBySerialNumber,  "54dba096", true);
    var certificate = certificates[0];
    
    // next three lines
    var cspParams = new CspParameters(24) { KeyContainerName = "XML_DSIG_RSA_KEY" };
    var key = new RSACryptoServiceProvider(cspParams);
    key.FromXmlString(certificate.PrivateKey.ToXmlString(true));
    
    SignedXml sxml = new SignedXml(doc);
    sxml.SigningKey = key;
    

    即使使用旧密钥,这个解决方案也能正常工作!

    【讨论】:

    • 很高兴知道有一个替代解决方案可以通过更改代码而不是证书来工作:) 选项越多越好
    • 答案对我有帮助。顺便说一句,XML_DISG_RSA_KEY 应该是 XML_DSIG_RSA_KEY 吧?
    • 是的,我想。感谢您的关注。
    • 体面的答案,但不能处理超过几个字节的数据来签名。
    • 我试过这样做,但它只是将我的异常更改为:“密钥在指定状态下无效”
    【解决方案2】:

    虽然这个问题是在大约一年前提出的,但最近获得了一些支持,这可能表明其他一些人也遇到了同样的问题。希望这个答案可以帮助:) 简而言之,错误不会发生在所有机器上,而只会发生在其中的一些机器上。我想这取决于在特定机器上注册了哪些 CSP。无论如何,在我的具体情况下,证书是使用“Microsoft RSA SChannel ...”或“Microsoft strong cryptographic provider”作为 CSP 生成的。我生成了一个新证书,但使用“Microsoft Enhanced RSA and AES Cryptographic Provider”作为 CSP,它的 SHA256 签名开始为我工作。

    一些参考资料:

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/e391ba75-ce6e-431c-bfc9-26a71ae1b033/sha256-signing-stops-working-in-net-45?forum=Geneva (如您所见,感谢 Paul 帮助我解决了这个问题)

    http://hintdesk.com/c-how-to-fix-invalid-algorithm-specified-when-signing-with-sha256/

    【讨论】:

      【解决方案3】:

      尽管这个问题已经很老了,但我很确定有人迟早会遇到它。

      最近,我们一直在处理在仅支持 TLS 1.2 并禁用 SHA-1 哈希算法的服务器上运行的服务。我们需要对整个 pain.something.something 文件进行签名,这会使最流行的答案变得毫无用处。

      这是我们发现的:

      1. 如果您使用证书私钥作为 SigningKey,则只能使用 SHA-1 算法进行签名。
      2. 您需要使用GetRSAPrivateKey方法获取私钥。
      3. 需要将signedXML的SignatureMethod设置为SecurityAlgorithms.RsaSha256Signature
      4. 需要将引用对象的DigestMethod设置为SecurityAlgorithms.Sha256Digest

      那么,你可以走了。 这里还有一个示例代码:

      private static void SignXmlDocumentEx(XmlElement el, X509Certificate2 cert)
      {
          var dataId = string.Format("Signature-{0}", Guid.NewGuid());
          var signedXml = new System.Security.Cryptography.Xml.SignedXml(el);
          signedXml.SigningKey = cert.GetRSAPrivateKey();
          signedXml.SignedInfo.SignatureMethod = SecurityAlgorithms.RsaSha256Signature;
          signedXml.Signature.Id = dataId;
          var reference = new Reference(dataId);
          reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
          reference.Uri = "";
          reference.DigestMethod = SecurityAlgorithms.Sha256Digest;
          signedXml.AddReference(reference);
          signedXml.KeyInfo = new KeyInfo();
          signedXml.KeyInfo.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.EndCertOnly));
          signedXml.ComputeSignature();
          el.AppendChild(signedXml.GetXml());
      }
      

      【讨论】:

        猜你喜欢
        • 2022-08-08
        • 2016-05-19
        • 1970-01-01
        • 2022-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多