【问题标题】:Why am I getting "Invalid algorithm specified" exception为什么我会收到“指定的算法无效”异常
【发布时间】:2011-11-17 23:38:05
【问题描述】:

这是我的代码。

X509Certificate pXCert = new X509Certificate2(@"keyStore.p12", "password");
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)pXCert.PrivateKey;
string id = CryptoConfig.MapNameToOID("SHA256");
return csp.SignData(File.ReadAllBytes(filePath), id);

在最后一行我得到了异常:

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

我做错了什么?

更新:

id = 2.16.840.1.101.3.4.2.1

【问题讨论】:

  • 我用 id 的值更新了问题。
  • 尝试使用 pXCert.GetRSAPrivateKey() 代替
  • 是的@thangcao,救命评论!我还要在 2020 年补充一点,对于 .NET 4.6 及更高版本,RSA 本身支持 SignData,如下所示:((RSA)cert.GetRSAPrivateKey()).SignData(bytes, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1)跨度>

标签: c# cryptography


【解决方案1】:

.NET 代码或您提供的 CSP 代码没有问题。

您的问题是 CSP 不支持 SHA 256。您可以获取更多信息here

【讨论】:

  • 有什么办法可以做到吗?我从 java 移植它,它需要使用相同的算法。据我所知,它正在使用 rsa + sha
  • 您可能需要检查msdn.microsoft.com/en-us/library/…,它是 .Net Framework 中的 SHA256 类。但是,我没用过。
  • SHA256CryptoServiceProvider 不接受非对称密钥
  • 此版本仅支持 SHA-256 用于对称密钥用途,例如 Kerberos 密钥,并且不使用 X.509 证书对消息进行签名。由于当前在 .NET Framework 3.0 中不支持 RSA-SHA256,WCF 不支持使用 SHA-256 哈希的 RSA 签名(在 X.509 证书中使用)(来源:msdn.microsoft.com/en-us/library/aa738624.aspx
【解决方案2】:

请注意,我使用的是 SHA512,但 SHA256 将适用于以下示例:

“指定的算法无效”我花了很长时间才弄清楚,我几乎尝试了所有方法。

第 1 步 - 证书必须是 SHA512 并使用支持 SHA512 的 CSP(加密服务提供商)。以下是 CSP 及其功能的列表。如果您寻找 SHA512,您会找到“Microsoft Enhanced RSA and AES Cryptographic Provider”。默认情况下生成证书不使用它(至少在 Windows 中),因此您必须在创建证书时指定它。

如果您使用 openssl 创建证书,您可以使用下面的选项 -CSP 设置正确的 CSP 以使其正常工作。如果您有现有的 pfx,可以使用 openssl 将其转换为 PEM 文件,然后再转换回 pfx 以添加选项。

创建私钥和证书 - 此步骤将询问您问题、州、地区等。

openssl req -x509 -nodes -sha512 -newkey rsa:2048 -keyout 512key.pem -out 512cert.pem -days 3650

使用 Microsoft 增强型 RSA 和 AES 加密提供程序创建 PFX 文件以导入您的证书存储:

openssl pkcs12 –export –in 512cert.pem –inkey 512key.pem –CSP “Microsoft Enhanced RSA and AES Cryptographic Provider” –out 512pfx.pfx

第 2 步: 支持 Gonzalo Gallotti 将链接发布到帮助我的代码段。我评论了我的代码以显示每个步骤在做什么。注意:如果没有步骤 1 中所述的正确生成的证书,此代码将无法工作

public void GetCertificate() {
    
    // Get the Machine Cert Store
    var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

    string alg = CryptoConfig.MapNameToOID("SHA512");

    // Open the cert store
    store.Open(OpenFlags.ReadWrite);

    // Loop through each certificate within the store
    foreach (X509Certificate2 myCert in store.Certificates)
    {
        // Get the certificate we are looking for
        if (myCert.IssuerName.Name.Contains("CN=YourSite"))
        {
            // Check if the certificate has a private key
            if (myCert.HasPrivateKey)
            {
                // Get your custom signature as a string
                string mySignature = GetSignatureString();

                // Convert signature to byte array
                byte[] originalData = Encoding.UTF8.GetBytes(mySignature);

                // Create RSA provider from private key
                RSACryptoServiceProvider rsaProvider = (RSACryptoServiceProvider)myCert.PrivateKey;

                // Sign the signature with SHA512
                byte[] signedSignature = signedSignature = rsaProvider.SignData(originalData, alg);

                if (rsaProvider.VerifyData(originalData, alg, signedSignature))
                {
                    // Signature is verified Do Stuff
                }
                else
                {
                    throw new Exception("The data does not match the signature.");
                }
            }
        }
    }
}

【讨论】:

  • 不知道对此的反对意见是什么......它确实帮助了我,非常感谢! +1 +1
  • @TjadClark 开头的冗长代码隐藏了答案的最后一部分,它描述了要进行的正确操作!我将进行编辑以纠正该问题
【解决方案3】:

遇到了类似的问题,但刚刚解决了。如果您不使用 X509 而只是使用普通的 RSACryptoServiceProvider 来获取密钥,则仅支持 SHA1。

【讨论】:

    【解决方案4】:

    对于 dot net framework 4.7.0 或更高版本不采用 sha1 因此在应用程序启动中配置以下内容。对我来说效果很好。

     AppContext.SetSwitch("Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms", true);
     AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);
    

    【讨论】:

      【解决方案5】:

      您可能在将应用程序从 .NET Framework 4.7 及更早版本迁移到 4.7.1 或更高版本时来到这里。
      如果您收到异常 System.Security.Cryptography.CryptographicException: Invalid algorithm specified.,原因是针对 .NET Framework 4.7.1 及更高版本的应用程序的默认 SignedXML 和 SignedXMS 算法更改为 SHA256 (from Microsoft .NET migration guide)

      在该指南中,您还可以找到解决方案:

      对于面向 .NET Framework 4.7.1 及更高版本的应用程序,如果不希望使用 SHA256,您可以通过将以下配置开关添加到应用配置文件的运行时部分来将默认设置恢复为 SHA1:

      <AppContextSwitchOverrides value="Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms=true;  
                        Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms=true" />
      

      但这可能并不总是有效,尤其是对于 Web 应用程序,正如您可以在此 blog post 中看到的那样,幸运的是,它也提供了答案。只需在Application_Start中添加几行即可

      protected void Application_Start(object sender, EventArgs e)
      {
         [...]
         AppContext.SetSwitch("Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms", true);
         AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);
      }
      

      【讨论】:

        【解决方案6】:

        您可以通过 appSettings 在 Web 配置中设置 AppContext 开关:

        <appSettings>
          <add key="AppContext.SetSwitch:Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms" value="true" />
          <add key="AppContext.SetSwitch:Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms" value="true" />
        </appSettings>
        

        【讨论】:

          【解决方案7】:

          可以使用 certutil 工具(在 Windows 上)检查您的证书使用的是哪个 CSP

          certutil yourCertificate.p12
          

          例子:

          • Microsoft Enhanced Cryptographic Provider v1.0 =>在 C# 4.7 及更高版本中抛出错误
          • Microsoft 增强的 RSA 和 AES 加密提供程序=> 有效

          【讨论】:

            【解决方案8】:

            我通过升级我的依赖项解决了这个问题。

            我不再依赖我之前使用多年的 GAC 版本,而是切换到最新的 NuGet 包 (v16.8.0):

            • Microsoft.Build.Tasks.Core
            • Microsoft.Build.Utilities.Core
            • Microsoft.Build.Framework

            这为我们解决了这个问题。

            【讨论】:

              猜你喜欢
              • 2016-08-08
              • 2016-05-13
              • 2013-11-08
              • 2013-02-10
              • 2014-07-01
              • 1970-01-01
              • 1970-01-01
              • 2010-10-15
              • 1970-01-01
              相关资源
              最近更新 更多