Цифровой знак с sha256 с c # - PullRequest
0 голосов
/ 11 октября 2018

здесь, в Италии, нам потребуется цифровая подпись всех счетов с января 2019 года.

Я нашел код, который хорошо работает с sha-1, но мне нужно использовать sha256 в качестве стандарта.Приведенный ниже код, после успешного определения USB-ключа и запроса сертификата для использования, попробуйте подписать файл «NomeFile» После и вывести в «NomeFile» .p7m, когда строка

signatureCms.ComputeSignature (signer,false);

выполняется, это происходит: 1 - если использовать sha-1, он запрашивает PIN-код и документ успешно создан.2 - если использовать sha-256, не спрашивайте PIN-код и выдает мне неизвестную ошибку -1073741275

Я прочитал много старых постов (2011-2014).У других людей такая же проблема, и кажется, что у Microsoft есть какая-то ошибка с использованием sha256.

Сейчас мы находимся в конце 2018 года, и я пробовал этот код в .net 4, 4.6.1 и 4.7.2, но ошибкато же самое.

Кто-нибудь может сказать мне, если Microsoft исправит проблему с sha256 и что это может быть за странная ошибка?(-1073741275) стек ошибок

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 версии OID signer.DigestAlgorithm = new Oid ("2.16.840.1.101.3.4.2.1");signer.DigestAlgorithm = new Oid ("SHA256");

Все 2 выдают одинаковую ошибку.

Я ИСПОЛЬЗУЮ USB-КЛЮЧ INFOCERT с драйвером bit4id (https://www.bit4id.com/it/4identity/), который содержитсяв USB-накопителе.

Ответы [ 4 ]

0 голосов
/ 19 октября 2018

Ошибка и симптом, по-видимому, указывают на то, что 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;
    }
}

Если сертификат фактически загружается из файла PFX на устройстве USB, проблема заключается в том, что PFX указывает использовать более старый программный CSP, предшествующий SHA-2.Восстановление PFX для использования новейшего CSP RSA также решит проблему.

0 голосов
/ 11 октября 2018

Я нашел это в интернете, я стараюсь, и это невероятно работает!В любом случае, решение немного сложнее.

Вы должны использовать библиотеку BouncyCastle (https://www.bouncycastle.org/)). Но не доступную версию, а версию, которая была изменена пользователем на другом форуме.

Ссылка на измененную библиотеку надувных замков: http://www.mediafire.com/download/uc63d1hepqyuhee/bccrypto-net-1.7-src-ext_with_CADES-BES.zip

Вы должны использовать библиотеку crypto.dll, находящуюся в bin \ release, и ссылаться на нее в своем проекте.

все, что я использую сейчас, вероятно, не все требуются для этого указанного случая:

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;
            }

        }

Редактировать: при повторном использовании с тем же сертификатом, он спрашиваетПИН только в первый раз. Поэтому хорошо сделать несколько файлов одновременно с активным стандартом безопасности.

0 голосов
/ 12 октября 2018

Гжегожу:

Исходный файл - 5 КБ. Правильный подписанный файл (IT01234567890_FPA01_2.xml.p7m - 8 КБ. Файл, сохраненный в вашей подпрограмме с добавлением

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

после

byte[] wynBin = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));

составляет всего 1 КБ и не распознается Дайком. Знак не распознается

Разница между файлами

0 голосов
/ 11 октября 2018

используйте это:

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;
}
...