Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带sha256和c的数字签名#_C#_Sha256_Sign - Fatal编程技术网

C# 带sha256和c的数字签名#

C# 带sha256和c的数字签名#,c#,sha256,sign,C#,Sha256,Sign,在意大利,自2019年1月起,我们需要对所有发票进行数字签名 我发现一个代码可以很好地与sha-1配合使用,但我需要使用sha256作为标准。 下面的代码,成功检测到USB密钥后,要求我使用证书尝试签名“NomeFile”文件后,输出在“NomeFile”.p7m,当行 签名CMS.计算签名(签名者,假) 运行时,会发生以下情况: 1-如果使用sha-1,它会要求我输入PIN,并成功创建文档。 2-如果使用sha-256,请不要询问PIN,并给出未知错误-1073741275 我读了很多老帖子(

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

我发现一个代码可以很好地与sha-1配合使用,但我需要使用sha256作为标准。 下面的代码,成功检测到USB密钥后,要求我使用证书尝试签名“NomeFile”文件后,输出在“NomeFile”.p7m,当行

签名CMS.计算签名(签名者,假)

运行时,会发生以下情况: 1-如果使用sha-1,它会要求我输入PIN,并成功创建文档。 2-如果使用sha-256,请不要询问PIN,并给出未知错误-1073741275

我读了很多老帖子(2011-2014)。其他人也有同样的问题,似乎微软在使用sha256时有一些缺陷

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

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

注:我试了两个版本的OID signer.DigestAlgorithm=新Oid(“2.16.840.1.101.3.4.2.1”); signer.DigestAlgorithm=新Oid(“SHA256”)

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

我使用USB驱动器中包含的带驱动程序bit4id()的INFOCERT USB密钥。

使用此项:

private string podpisz(X509Certificate2 cert, string toSign)
{
    string output = "";

    try
    {
        RSACryptoServiceProvider csp = null;
        csp = (RSACryptoServiceProvider)cert.PrivateKey;

        // Hash the data
        SHA256Managed sha256 = new SHA256Managed();
        UnicodeEncoding encoding = new UnicodeEncoding();
        byte[] data = Encoding.Default.GetBytes(toSign);
        byte[] hash = sha256.ComputeHash(data);

        // Sign the hash
        byte[] wynBin = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
        output = Convert.ToBase64String(wynBin);

    }
    catch (Exception)
    {

    }

    return output;
}
使用以下命令:

private string podpisz(X509Certificate2 cert, string toSign)
{
    string output = "";

    try
    {
        RSACryptoServiceProvider csp = null;
        csp = (RSACryptoServiceProvider)cert.PrivateKey;

        // Hash the data
        SHA256Managed sha256 = new SHA256Managed();
        UnicodeEncoding encoding = new UnicodeEncoding();
        byte[] data = Encoding.Default.GetBytes(toSign);
        byte[] hash = sha256.ComputeHash(data);

        // Sign the hash
        byte[] wynBin = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
        output = Convert.ToBase64String(wynBin);

    }
    catch (Exception)
    {

    }

    return output;
}

我在互联网上找到了这个,我尝试了一下,难以置信的是它成功了! 无论如何,解决方案要复杂一点

您必须使用BouncyCastle()库。 但不是可用的版本,而是由其他论坛上的用户修改的版本

到bouncy castle库的链接已修改为:

您必须使用bin\release中的crypto.dll库,并在项目中引用它

这些都是我现在使用的,可能不是所有都需要用于此特定情况:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Xml;
using System.IO;
using System.Collections;
using CryptoUpgNet.NonExportablePK;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Ess;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
这就是功能:

public byte[] FirmaFileBouncy(String NomeFile, X509Certificate2 cert, ref string RisFirma)
        {
            String NomeFirma = NomeFile + ".p7m";

            try
            {
                SHA256Managed hashSha256 = new SHA256Managed();
                byte[] certHash = hashSha256.ComputeHash(cert.RawData);

                EssCertIDv2 essCert1 = new EssCertIDv2(new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier("2.16.840.1.101.3.4.2.1"), certHash);
                SigningCertificateV2 scv2 = new SigningCertificateV2(new EssCertIDv2[] { essCert1 });

                Org.BouncyCastle.Asn1.Cms.Attribute CertHAttribute = new Org.BouncyCastle.Asn1.Cms.Attribute(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdAASigningCertificateV2, new DerSet(scv2));
                Asn1EncodableVector v = new Asn1EncodableVector();
                v.Add(CertHAttribute);

                Org.BouncyCastle.Asn1.Cms.AttributeTable AT = new Org.BouncyCastle.Asn1.Cms.AttributeTable(v);
                CmsSignedDataGenWithRsaCsp cms = new CmsSignedDataGenWithRsaCsp();

                dynamic rsa = (RSACryptoServiceProvider)cert.PrivateKey;
                Org.BouncyCastle.X509.X509Certificate certCopy = DotNetUtilities.FromX509Certificate(cert);
                cms.MyAddSigner( rsa, certCopy,  "1.2.840.113549.1.1.1", "2.16.840.1.101.3.4.2.1", AT, null);

                ArrayList certList = new ArrayList();
                certList.Add(certCopy);

                Org.BouncyCastle.X509.Store.X509CollectionStoreParameters PP = new Org.BouncyCastle.X509.Store.X509CollectionStoreParameters(certList);
                Org.BouncyCastle.X509.Store.IX509Store st1 = Org.BouncyCastle.X509.Store.X509StoreFactory.Create("CERTIFICATE/COLLECTION", PP);

                cms.AddCertificates(st1);

                //mi ricavo il file da firmare
                FileInfo File__1 = new FileInfo(NomeFile);
                CmsProcessableFile file__2 = new CmsProcessableFile(File__1);
                CmsSignedData Firmato = cms.Generate(file__2, true);
                byte[] Encoded = Firmato.GetEncoded();

                File.WriteAllBytes(NomeFirma, Encoded);

                RisFirma = "true";

                return Encoded;

            } catch (Exception ex)  {

                RisFirma = ex.ToString();
                return null;
            }

        }

编辑:使用同一证书重复使用,仅第一次询问PIN。所以,在安全标准处于活动状态的情况下,一次创建多个文件是很好的。

我在互联网上找到了这个方法,我尝试了一下,效果令人难以置信! 无论如何,解决方案要复杂一点

您必须使用BouncyCastle()库。 但不是可用的版本,而是由其他论坛上的用户修改的版本

到bouncy castle库的链接已修改为:

您必须使用bin\release中的crypto.dll库,并在项目中引用它

这些都是我现在使用的,可能不是所有都需要用于此特定情况:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Xml;
using System.IO;
using System.Collections;
using CryptoUpgNet.NonExportablePK;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Ess;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
这就是功能:

public byte[] FirmaFileBouncy(String NomeFile, X509Certificate2 cert, ref string RisFirma)
        {
            String NomeFirma = NomeFile + ".p7m";

            try
            {
                SHA256Managed hashSha256 = new SHA256Managed();
                byte[] certHash = hashSha256.ComputeHash(cert.RawData);

                EssCertIDv2 essCert1 = new EssCertIDv2(new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier("2.16.840.1.101.3.4.2.1"), certHash);
                SigningCertificateV2 scv2 = new SigningCertificateV2(new EssCertIDv2[] { essCert1 });

                Org.BouncyCastle.Asn1.Cms.Attribute CertHAttribute = new Org.BouncyCastle.Asn1.Cms.Attribute(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdAASigningCertificateV2, new DerSet(scv2));
                Asn1EncodableVector v = new Asn1EncodableVector();
                v.Add(CertHAttribute);

                Org.BouncyCastle.Asn1.Cms.AttributeTable AT = new Org.BouncyCastle.Asn1.Cms.AttributeTable(v);
                CmsSignedDataGenWithRsaCsp cms = new CmsSignedDataGenWithRsaCsp();

                dynamic rsa = (RSACryptoServiceProvider)cert.PrivateKey;
                Org.BouncyCastle.X509.X509Certificate certCopy = DotNetUtilities.FromX509Certificate(cert);
                cms.MyAddSigner( rsa, certCopy,  "1.2.840.113549.1.1.1", "2.16.840.1.101.3.4.2.1", AT, null);

                ArrayList certList = new ArrayList();
                certList.Add(certCopy);

                Org.BouncyCastle.X509.Store.X509CollectionStoreParameters PP = new Org.BouncyCastle.X509.Store.X509CollectionStoreParameters(certList);
                Org.BouncyCastle.X509.Store.IX509Store st1 = Org.BouncyCastle.X509.Store.X509StoreFactory.Create("CERTIFICATE/COLLECTION", PP);

                cms.AddCertificates(st1);

                //mi ricavo il file da firmare
                FileInfo File__1 = new FileInfo(NomeFile);
                CmsProcessableFile file__2 = new CmsProcessableFile(File__1);
                CmsSignedData Firmato = cms.Generate(file__2, true);
                byte[] Encoded = Firmato.GetEncoded();

                File.WriteAllBytes(NomeFirma, Encoded);

                RisFirma = "true";

                return Encoded;

            } catch (Exception ex)  {

                RisFirma = ex.ToString();
                return null;
            }

        }
编辑:使用同一证书重复使用,仅第一次询问PIN。因此,在安全标准处于活动状态的情况下,一次创建多个文件很好。

致Grzegorz:

源文件是5k 正确的签名文件(IT01234567890_FPA01_2.xml.p7m)为8k 与例程一起保存的文件添加了

File.WriteAllBytes("c:\\temp\\IT01234567890_FPA01.xml.p7m", wynBin);
之后

仅1kb,未被堤坝识别。

致格泽戈兹:

源文件是5k 正确的签名文件(IT01234567890_FPA01_2.xml.p7m)为8k 与例程一起保存的文件添加了

File.WriteAllBytes("c:\\temp\\IT01234567890_FPA01.xml.p7m", wynBin);
之后

仅1kb,未被堤坝识别。


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

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

...
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也可以解决问题。

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

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

...
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也可以解决问题。

该代码看起来像Java。如果不正确,请自己编辑标记。@Someprogrammerdude感谢您的更正。@Someprogrammerdude感谢您的更正。@MagoMaverick您解决过这个问题吗?使用
SignedCms
和ncipher HSM遇到了非常类似的错误。这些代码看起来像Java。如果不正确,请自己编辑您的标记。@Someprogrammerdude感谢您的更正。@MagoMaverick您解决过这个问题吗?Experience使用
SignedCms
和一个ncipher-HSM检查非常类似的错误。
csp=null
然后
csp.SignHash
?什么?以及
cert
的意义是什么?csp为null,所以行字节[]wynBin=csp。SignHash(…)给出错误。我丢失了csp=(RSACryptoServiceProvider)cert.PrivateKey;依我看,一个空的
catch
块总是一个不好的建议。@GrzegorzJ我尝试了一下,它正确地询问了我PIN,完成签名后,wynBin的内容不是完整的已签名文件,而是少于1k的文件。可能需要做些什么来保存已签名的源文件。p7m格式
csp=null
,然后
csp.SignHash
?什么?证书的意义是什么?csp为空,因此行字节[]wynBin=csp。SignHash(…)给出错误。我丢失了csp=(RSACryptServiceProvider)cert.PrivateKey;依我看,一个空的
catch
块总是一个不好的建议。@GrzegorzJ我试过了,它正确地询问了我PIN码,完成签名后,wynBin的内容不是完整的签名文件,但只有不到1k的文件。可能需要做些什么来保存已签名的源文件。p7m格式谢谢@bartonjs,我将在下一步中尝试我从.NETCoreAPI服务调用这段代码,您的回答修复了引发的异常(无效类型)