使用 c# 使用 sha256 进行数字签名 [英] Digital sign with sha256 with c#

查看:477
本文介绍了使用 c# 使用 sha256 进行数字签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在意大利,自 2019 年 1 月起,我们将需要对所有发票进行数字签名.

here in Italy, we will need to digitally sign all invoices since January 2019.

我发现了一个适用于 sha-1 的代码,但我需要使用 sha256 作为标准.下面的代码,在成功检测到USB密钥后,并要求我使用的证书尝试签署NomeFile"文件后并在NomeFile".p7m中输出,当行

I found a code that works well with sha-1, but I need to use sha256 as standard. The code below, after successfully detect USB key, and ask me for the certificate to use try to sign "NomeFile" file After and output in "NomeFile".p7m, when the line

signedCms.ComputeSignature(signer,false);

signedCms.ComputeSignature(signer,false);

运行,它发生:1- 如果使用 sha-1,它会要求我输入 PIN 并成功创建文档.2- 如果使用 sha-256 不要求输入 PIN 并给我未知错误 -1073741275

runs, it happens: 1- if use sha-1 it asks me for the PIN and document is successfully created. 2- if use sha-256 don't ask for PIN and gives me Unknown error -1073741275

我阅读了很多旧帖子(2011-2014).其他人也有同样的问题,似乎微软在使用 sha256 时有一些错误.

I read a lot of posts that are all old (2011-2014). Other people have the same problem and seem that Microsoft has some bug using sha256.

现在是 2018 年底,我在 .net 4、4.6.1 和 4.7.2 中尝试了这段代码,但错误是一样的.

Now we are at end of 2018 and I tried this code in .net 4, 4.6.1 and 4.7.2 but the error is the same.

有人可以告诉我微软是否纠正了 sha256 的问题,这个奇怪的错误是什么?(-1073741275)错误堆栈

Somebody can tell me if Microsoft corrects the problem with sha256 and what could be this strange error? (-1073741275) Error Stack

public String FirmaFile(String NomeFile, DateTime DataFirma, X509Certificate2 cert, out string RisFirma)
        {
            String NomeFirma = NomeFile + ".p7m";
            RisFirma = "";

            try
            {


                // content contiene il file da firmare
                ContentInfo content = new ContentInfo((File.ReadAllBytes(NomeFile)));
                // assegniamo content ad un oggetto di tipo SignedCms
                SignedCms signedCms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber, content, false);

                // si instanzia un oggetto CmsSigner che espone i metodi di firma.
                CmsSigner signer = new CmsSigner(cert);
                signer.IncludeOption = X509IncludeOption.EndCertOnly;

                //signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
                signer.DigestAlgorithm = new Oid("SHA256");
                signer.SignedAttributes.Add(new Pkcs9SigningTime(DataFirma));
                try
                {
                    // Viene calcolata la firma del file (in formato PKCS7)
                    signedCms.ComputeSignature(signer,false);
                }
                catch (CryptographicException CEx)
                {
                    RisFirma = "Errore: " + CEx.Message + " Stack: " + CEx.StackTrace;
                    return RisFirma;
                }
                // si pone il file firmato in un array.
                byte[] signature = signedCms.Encode();
                File.WriteAllBytes(NomeFirma, signature);
                RisFirma = "true";
            }
            catch (Exception Ex)
            {
                RisFirma = "Errore in FirmaFile: " + Ex.Message + " Stack: " + Ex.StackTrace;
            }
            return RisFirma;
        }

注意:我尝试了 2 个版本的 OIDsigner.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");signer.DigestAlgorithm = new Oid("SHA256");

NB: I tried 2 version of OID signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1"); signer.DigestAlgorithm = new Oid("SHA256");

所有 2 都给出相同的错误.

All 2 give the same error.

我使用带有驱动程序 bit4id 的 INFOCERT USB KEY (https://www.bit4id.com/it/4identity/) 包含在 USB 驱动器中.

I USE an INFOCERT USB KEY with driver bit4id (https://www.bit4id.com/it/4identity/) that is contained in USB Drive.

推荐答案

该错误和症状似乎表明正在执行签名操作的 CSP(加密服务提供程序)不支持 SHA-2.如果它在 BouncyCastle 中运行,那么他们似乎在导出私钥并将其重新导入到他们的软件提供商中.

The error and symptom seem to indicate that the CSP (Cryptographic Service Provider) which is doing the signing operation doesn't support SHA-2. If it's working in BouncyCastle then they are seemingly exporting the private key and re-importing it into their software provider.

在 .NET 4.7.2 中,您可以尝试以下操作:

In .NET 4.7.2 you could try the following:

...
try
{
    // Viene calcolata la firma del file (in formato PKCS7)
    signedCms.ComputeSignature(signer,false);
}
catch (CryptographicException CEx)
{
    try
    {
        // Try re-importing the private key into a better CSP:
        using (RSA tmpRsa = RSA.Create())
        {
            tmpRsa.ImportParameters(cert.GetRSAPrivateKey().ExportParameters(true));

            using (X509Certificate2 tmpCertNoKey = new X509Certificate2(cert.RawData))
            using (X509Certificate2 tmpCert = tmpCertNoKey.CopyWithPrivateKey(tmpRsa))
            {
                signer.Certificate = tmpCert;
                signedCms.ComputeSignature(signer,false);
            }
        }
    }
    catch (CryptographicException)
    {
        // This is the original exception, not the inner one.
        RisFirma = "Errore: " + CEx.Message + " Stack: " + CEx.StackTrace;
        return RisFirma;
    }
}

如果证书实际上是从 USB 设备上的 PFX 文件加载的,则问题在于 PFX 指定使用早于 SHA-2 的旧软件 CSP.重新生成 PFX 以使用最新的 RSA CSP 也可以解决问题.

If the certificate is actually being loaded from a PFX file on the USB device, then the problem is that the PFX specifies to use an older software CSP which predated SHA-2. Getting the PFX regenerated to use the newest RSA CSP would also solve the problem.

这篇关于使用 c# 使用 sha256 进行数字签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆