SHA256签名在.NET 4.5中停止运行

时间:2013-10-27 17:18:49

标签: .net certificate wif signing sha256

我们有一段代码创建了一个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

3 个答案:

答案 0 :(得分:15)

与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)。
令我惊讶的是,这个新证书让我成功签名。

经过一番调查后,我在这里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;

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

答案 1 :(得分:3)

虽然这个问题差不多在一年前提出,但它最近收到了一些投票,这可能表明其他一些人也遇到了同样的问题。希望这个答案可以帮助:) 简而言之,错误并非在所有机器中发生,而只在其中一些机器中发生。我想这取决于在特定机器上注册的CSP。无论如何,在我的具体情况下,证书是使用" Microsoft RSA SChannel生成的......"或者" Microsoft强大的加密提供商"作为CSP。我生成了一个新证书,但使用了" Microsoft增强型RSA和AES加密提供商"正如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/

答案 2 :(得分:0)

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

最近,我们一直在处理仅在支持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());
}