Dot-Net

SHA256 簽名在 .NET 4.5 中停止工作

  • March 12, 2019

我們有一段程式碼創建了一個 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

雖然這個問題是在大約一年前提出的,但最近收到了一些贊成票,這可能表明其他一些人也遇到了同樣的問題。希望這個答案可以幫助:) 簡而言之,錯誤不會發生在所有機器上,而只會發生在其中一些機器上。我想這取決於在特定機器上註冊了哪些 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/>

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:指定的算法無效。

這讓我想到了你的問題。閱讀建議的文章後,我使用Microsoft Enhanced RSA and AES Cryptographic Provider.

令我驚訝的是,這個新證書使我能夠成功地進行簽名。

經過更多調查後,我在這裡找到了 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;

即使使用舊鑰匙,這個解決方案也能正常工作!

引用自:https://stackoverflow.com/questions/19620970