简体   繁体   English

为什么我会收到“指定的算法无效”异常

[英]Why am I getting "Invalid algorithm specified" exception

Here is my code.这是我的代码。

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

On the last line I'm getting the exception:在最后一行我得到了例外:

System.Security.Cryptography.CryptographicException "Invalid algorithm specified." System.Security.Cryptography.CryptographicException “指定的算法无效。”

What am I doing wrong?我究竟做错了什么?

UPDATE:更新:

id = 2.16.840.1.101.3.4.2.1 id = 2.16.840.1.101.3.4.2.1

For dot net framework 4.7.0 or higher is not taking the sha1 so configure the below in application start.对于 dot net framework 4.7.0 或更高版本不采用 sha1,因此在应用程序启动中配置以下内容。 it's worked fine for me.它对我来说很好。

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

There is no issue with .NET code or the CSP code you provided. .NET 代码或您提供的 CSP 代码没有问题。

Your problem is that CSP just doesn't support SHA 256. You can get further information here您的问题是 CSP 不支持 SHA 256。您可以在此处获取更多信息

Note that I use SHA512 but SHA256 will work with the below examples:请注意,我使用 SHA512,但 SHA256 将适用于以下示例:

"Invalid algorithm specified" Took me forever to figure out and I tried practically everything. “指定的算法无效”我花了很长时间才弄清楚,我几乎尝试了所有方法。

Step 1 - the certificate has to be SHA512 and use a CSP (Cryptographic Service Provider) that is SHA512 Capable.第 1 步- 证书必须是 SHA512 并使用支持 SHA512 的 CSP(加密服务提供商)。 Here is a list of CSPs and their capabilities.以下是 CSP 及其功能的列表。 If you look for SHA512 you'll find the "Microsoft Enhanced RSA and AES Cryptographic Provider".如果您寻找 SHA512,您会找到“Microsoft Enhanced RSA and AES Cryptographic Provider”。 By default generating certificates don't use this (at least in Windows) so you have to specify it when you create the certificate.默认情况下生成证书不使用它(至少在 Windows 中),因此您必须在创建证书时指定它。

If you create the certificate with openssl, you can use the option -CSP below to set the correct CSP that will make it work.如果您使用 openssl 创建证书,则可以使用下面的选项 -CSP 来设置正确的 CSP 以使其正常工作。 If you have an existing pfx, you can convert it to a PEM file with openssl, and then back to a pfx to add the option.如果您有现有的 pfx,则可以使用 openssl 将其转换为 PEM 文件,然后再转换回 pfx 以添加选项。

Create private key and certificate - this step will ask you questions, state, region etc etc.创建私钥和证书 - 此步骤将询问您问题、州、地区等。

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

Create PFX file to import into your certificate store using the Microsoft Enhanced RSA and AES Cryptographic Provider:使用 Microsoft 增强型 RSA 和 AES 加密提供程序创建 PFX 文件以导入您的证书存储:

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

Step 2 : Props to Gonzalo Gallotti for posting the link to the piece of code that helped me.第 2 步:支持 Gonzalo Gallotti 将链接发布到帮助我的代码段。 I commented up my code to show what each step is doing.我评论了我的代码以显示每个步骤在做什么。 NOTE: this code won't work without a properly generated certificate as described in step 1注意:如果没有正确生成的证书,如步骤 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.");
                }
            }
        }
    }
}

You might have come here while you are migrating your application from .NET Framework 4.7 and earlier versions to 4.7.1 or later versions.您可能在将应用程序从 .NET Framework 4.7 及更早版本迁移到 4.7.1 或更高版本时来到这里。
If you are getting the exception System.Security.Cryptography.CryptographicException: Invalid algorithm specified.如果您收到异常System.Security.Cryptography.CryptographicException: Invalid algorithm specified. , the reason is that default SignedXML and SignedXMS algorithms changed to SHA256 for applications that target the .NET Framework 4.7.1 and later versions ( from Microsoft .NET migration guide ) ,原因是针对 .NET Framework 4.7.1 及更高版本的应用程序的默认 SignedXML 和 SignedXMS 算法更改为 SHA256( 来自 Microsoft .NET 迁移指南

In that guide you'll also find the solution:在该指南中,您还将找到解决方案:

For applications that target the .NET Framework 4.7.1 and later versions, if the use of SHA256 is undesirable, you can restore the default to SHA1 by adding the following configuration switch to the runtime section of your app config file:对于面向 .NET Framework 4.7.1 及更高版本的应用程序,如果不希望使用 SHA256,您可以通过将以下配置开关添加到应用程序配置文件的运行时部分来将默认设置恢复为 SHA1:

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

But this may not always work, especially for web applications, as you can read in this blog post , fortunately along with the answer as well.但这可能并不总是有效,特别是对于 Web 应用程序,正如您可以在这篇文中看到的那样,幸运的是,它也提供了答案。 It is only necessary to add some lines in the Application_Start只需在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);
}

Which CSP your certificate is using can be checked with certutil tool (on windows)可以使用 certutil 工具(在 Windows 上)检查您的证书正在使用哪个 CSP

certutil yourCertificate.p12

在此处输入图像描述

Examples:例子:

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

Having a similar issue but just resolved it.有类似的问题,但刚刚解决了。 If you are not using X509 but just the plain RSACryptoServiceProvider to get the keys, then only SHA1 is supported.如果您不使用 X509 而只是使用普通的 RSACryptoServiceProvider 来获取密钥,则仅支持 SHA1。

You can set the AppContext switches in a web config via appSettings:您可以通过 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>

I fixed the issue by upgrading my dependencies.我通过升级我的依赖项解决了这个问题。

Instead of relying on the GAC version I was previously using for years, I switched to the latest NuGet packages (v16.8.0) of:我没有依赖我以前使用多年的 GAC 版本,而是切换到最新的 NuGet 包 (v16.8.0):

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

This fixed this issue for us.这为我们解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我得到一个无效的转换异常(“指定的转换无效。”)? - Why am I getting an invalid cast exception ('Specified cast is not valid.')? 为什么使用此SQLite代码会收到“无效的转换异常”? - Why am I getting “Invalid Cast Exception” with this SQLite code? 为什么我得到这个例外 - Why am I getting this exception 我在调用 GetRSAPrivateKey 时指定了无效的提供程序类型 - I am getting an Invalid provider type specified on call to GetRSAPrivateKey 为什么我在文本框中得到无效的输出? - Why am I getting invalid output in textbox? 为什么我会收到带有消息“非虚拟(在 VB 中可覆盖)成员上的设置无效...”的异常? - Why am I getting an Exception with the message “Invalid setup on a non-virtual (overridable in VB) member…”? 为什么我使用以下代码获得异常? - Why am I getting an exception with the following code? 为什么会出现“参数无效”异常? - Why am I getting a 'parameter not valid' exception? 为什么会出现此Stack Overflow异常? - Why am I getting this Stack Overflow exception? 为什么我没有得到空引用异常? - Why am I NOT getting a Null Reference Exception?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM