none
FIRMA DIGITALE .P7M CADES RRS feed

  • Domanda

  • hi

    I would Like to sign a file with PKCS7 SHA256 CADES-BES specifications.

    Now I'm signing with following code with SHA256 but the result isnot CADES-BES compliances.

    following the code tha I'm Using now.

     

      private void button1_Click(object sender, EventArgs e)
      {
       //mi seleziono il certificato
       X509Store st = new X509Store(StoreName.My, StoreLocation.CurrentUser);
       st.Open(OpenFlags.ReadOnly);
       X509Certificate2Collection col = st.Certificates;
       X509Certificate2 card = null;
       X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(col, "Certificates", "Select one to sign", X509SelectionFlag.SingleSelection);
       if (sel.Count > 0)
       {
        X509Certificate2Enumerator en = sel.GetEnumerator();
        en.MoveNext();
        card = en.Current;
       }
       st.Close();
    
       if (card != null)
       {
        //scelgo il file da firmare
        openFileDialog1.ShowDialog();
        if (!string.IsNullOrEmpty(openFileDialog1.FileName))
        {
         //firmo il file
         string Res = "";
         FirmaFile(openFileDialog1.FileName, DateTime.UtcNow, card, out Res);
         if (Res == "true")
         {
          MessageBox.Show("Firma Con Successo");
         }
         else
         {
          MessageBox.Show(Res);
         }
        }
       }
      }
    
    
      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.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
        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;
      }
    
    

     

    The question is how can I obtain CADES-BES ?

    thanking for help

    Piercarlo


    martedì 12 luglio 2011 07:18

Risposte

  • Eccomi di Nuovo:

    Allora ho risolto qualcosa ed ho ancora qualche domanda

    Sono riuscito a firmare con le dll bouncy castle con le specifiche CADES-BES senza alcun problema (di seguito posto il codice per chi ne abbia bisogno)

    Ho solo bisogno del seguente aiuto:

    Allora :

    Vorrei passare al CSP la password programmaticamente.

    Con questo sistema se ho più certificati di firma con più chiavette inserite nel computer mi viene sempre presa la prima chiavetta USB con conseguente errore se non contiene il certificato giusto, vorrei essere in grado di selezionarle in base al certificato in esse contenuto.

    Di seguito il codice che ho usato:

    Per Selezionare il certificato e scrivere il file:

        private void button1_Click(object sender, EventArgs e)
        {
          try
          {
            //mi seleziono il certificato
            X509Store st = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            st.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection col = st.Certificates;
            X509Certificate2 card = null;
            X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(col, "Certificates", "Select one to sign", X509SelectionFlag.SingleSelection);
            if (sel.Count > 0)
            {
              X509Certificate2Enumerator en = sel.GetEnumerator();
              en.MoveNext();
              card = en.Current;
            }
            st.Close();
    
            if (card != null)
            {
              openFileDialog1.ShowDialog();
              if (!string.IsNullOrEmpty(openFileDialog1.FileName))
              {
                string Res = "";
                string NomeFile = openFileDialog1.FileName;
                byte[] Firmato = FirmaFileBouncy(NomeFile, card, out Res);
                if (string.IsNullOrEmpty(Res))
                {
                  File.WriteAllBytes(NomeFile + ".p7m", Firmato);
                  MessageBox.Show("Messaggio Firmato Con Successo");
                }
                else
                {
                  throw new Exception(Res);
                }
              }
            }
          }
          catch (Exception ex)
          {
            MessageBox.Show(ex.ToString());
          }
        }
    

    per firmare il file con le crypto bouncy

        public byte[] FirmaFileBouncy(String NomeFile, X509Certificate2 cert, out string RisFirma)
        {
          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();
    
            var 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 = new FileInfo(NomeFile);
            CmsProcessableFile file = new CmsProcessableFile(File);
            CmsSignedData Firmato = cms.Generate(file, true);
            byte[] Encoded = Firmato.GetEncoded();
            RisFirma = "";
            return Encoded;
          }
          catch (Exception ex)
          {
            RisFirma = ex.ToString();
            return null;
          }
        }
    

    Per farequesto bisogna scaricare il sorgente dal sito di bouncyCasle "bccrypto-net-1.7-src-ext.zip"

    inserire la seguente classe:

    using System;
    using System.Collections;
    using System.IO;
    
    using Org.BouncyCastle.Asn1;
    using Asn1 = Org.BouncyCastle.Asn1;
    using Org.BouncyCastle.Asn1.Cms;
    using Org.BouncyCastle.Asn1.X509;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.Security.Certificates;
    using Org.BouncyCastle.X509;
    using Org.BouncyCastle.Cms;
    using NetCrypto = System.Security.Cryptography;
    
    namespace CryptoUpgNet.NonExportablePK
    {
      public class CmsSignedDataGenWithRsaCsp
        : CmsSignedGenerator
      {
    		private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
    
    		private readonly ArrayList signerInfs = new ArrayList();
    
    		private class SignerInf
        {
          private readonly CmsSignedGenerator outer;
    
    			private readonly AsymmetricKeyParameter		key;
          private readonly NetCrypto.RSACryptoServiceProvider krProv;
    			private readonly SignerIdentifier			signerIdentifier;
    			private readonly string						digestOID;
    			private readonly string						encOID;
    			private readonly CmsAttributeTableGenerator	sAttr;
    			private readonly CmsAttributeTableGenerator	unsAttr;
    			private readonly Asn1.Cms.AttributeTable	baseSignedTable;
    
          /// <summary>
          /// Signer is received with crypto provider or pr. key (if the crypto provider == null)
          /// </summary>
          /// <param name="krProv">Crypto provider. if null than use key</param>
          /// <param name="key">Private key</param>
    			internal SignerInf(
            CmsSignedGenerator			outer,
            NetCrypto.RSACryptoServiceProvider krProv,
    	      AsymmetricKeyParameter		key,
    	      SignerIdentifier			signerIdentifier,
    	      string						digestOID,
    	      string						encOID,
    	      CmsAttributeTableGenerator	sAttr,
    	      CmsAttributeTableGenerator	unsAttr,
    	      Asn1.Cms.AttributeTable		baseSignedTable)
    	    {
            this.outer = outer;
            this.key = key;
            this.krProv = krProv;
            this.signerIdentifier = signerIdentifier;
            this.digestOID = digestOID;
            this.encOID = encOID;
    	      this.sAttr = sAttr;
    	      this.unsAttr = unsAttr;
    	      this.baseSignedTable = baseSignedTable;
          }
    
    			internal AlgorithmIdentifier DigestAlgorithmID
    			{
    				get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
    			}
    
    			internal CmsAttributeTableGenerator SignedAttributes
          {
    				get { return sAttr; }
          }
    
          internal CmsAttributeTableGenerator UnsignedAttributes
          {
    				get { return unsAttr; }
          }
    
    			internal SignerInfo ToSignerInfo(
            DerObjectIdentifier	contentType,
            CmsProcessable		content,
    				SecureRandom		random,
    				bool				isCounterSignature)
          {
            AlgorithmIdentifier digAlgId = DigestAlgorithmID;
            string digestName = Helper.GetDigestAlgName(digestOID);
            
            IDigest dig = Helper.GetDigestInstance(digestName);
    
            string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
            //ISigner sig moved there where used
    
            // TODO Optimise the case where more than one signer with same digest
            if (content != null)
            {
              content.Write(new DigOutputStream(dig));
            }
    
            byte[] hash = DigestUtilities.DoFinal(dig);
            outer._digests.Add(digestOID, hash.Clone());
    
            Asn1Set signedAttr = null;
            byte[] tmp;
            if (sAttr != null)
            {
              IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
    
              //					Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
              Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters);
    
              if (isCounterSignature)
              {
                Hashtable tmpSigned = signed.ToHashtable();
                tmpSigned.Remove(CmsAttributes.ContentType);
                signed = new Asn1.Cms.AttributeTable(tmpSigned);
              }
    
              // TODO Validate proposed signed attributes
    
              signedAttr = outer.GetAttributeSet(signed);
    
              // sig must be composed from the DER encoding.
              tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
            }
            else
            {
              // TODO Use raw signature of the hash value instead
              MemoryStream bOut = new MemoryStream();
              if (content != null)
              {
                content.Write(bOut);
              }
              tmp = bOut.ToArray();
            }
    
            byte[] sigBytes = null;
            if (krProv != null)
            {
              /*
              sig.GenerateSignature() supports the following hashes:
              MD2
              MD4
              MD5
              SHA1
              SHA224
              SHA256
              SHA384
              SHA512
              RIPEMD128
              RIPEMD160
              RIPEMD256
              *
              krProv.SignData(tmp, digestName) supports the following digestName:
              MD5
              SHA1
              SHA256
              SHA384
              SHA512
              */
    
              //sigBytes = krProv.SignData(tmp, digestName);
    
              IDigest digProv = Helper.GetDigestInstance(digestName);
              digProv.BlockUpdate(tmp, 0, tmp.Length);
              byte[] hashProv = new byte[digProv.GetDigestSize()];
              digProv.DoFinal(hashProv, 0);
    
              sigBytes = krProv.SignHash(hashProv, digestOID);
    
            }
            else
            {
              ISigner sig = Helper.GetSignatureInstance(signatureName);//was moved
              sig.Init(true, new ParametersWithRandom(key, random));
              sig.BlockUpdate(tmp, 0, tmp.Length);
              sigBytes = sig.GenerateSignature();
            }
            
            Asn1Set unsignedAttr = null;
            if (unsAttr != null)
            {
              IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
              baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();
    
              //					Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
              Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);
    
              // TODO Validate proposed unsigned attributes
    
              unsignedAttr = outer.GetAttributeSet(unsigned);
            }
    
            // TODO [RSAPSS] Need the ability to specify non-default parameters
            Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
            AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
              new DerObjectIdentifier(encOID), sigX509Parameters);
    
            return new SignerInfo(signerIdentifier, digAlgId,
              signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
          }
        }
    
    		public CmsSignedDataGenWithRsaCsp()
        {
        }
    
    		/// <summary>Constructor allowing specific source of randomness</summary>
    		/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
    		public CmsSignedDataGenWithRsaCsp(
    			SecureRandom rand)
    			: base(rand)
    		{
    		}
    
        /// <summary>
        /// add a signer - no attributes other than the default ones will be provided here для RSACryptoServiceProvider
        /// </summary>
        /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
        /// <param name="cert">cert certificate containing corresponding public key</param>
        /// <param name="digestOID">digestOID digest algorithm OID</param>
        public void AddSigner(
          NetCrypto.RSACryptoServiceProvider	crProv,
          X509Certificate			cert,
          string					digestOID)
        {
        	AddSigner(crProv, cert, GetEncOid(crProv, digestOID), digestOID);
    		}
    
    		/// <summary>
    		/// add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be provided here.
    		/// </summary>
        /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
        /// <param name="cert">certificate containing corresponding public key</param>
        /// <param name="encryptionOID">digest encryption algorithm OID</param>
        /// <param name="digestOID">digest algorithm OID</param>
    		public void AddSigner(
          NetCrypto.RSACryptoServiceProvider crProv,
    			X509Certificate			cert,
    			string					encryptionOID,
    			string					digestOID)
    		{
    			signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(cert), digestOID, encryptionOID,
    				new DefaultSignedAttributeTableGenerator(), null, null));
    		}
    
    		/// <summary>
        /// add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators
    		/// </summary>
    		public void AddSigner(
          NetCrypto.RSACryptoServiceProvider crProv,
    			byte[]						subjectKeyID,
    			string						encryptionOID,
    			string						digestOID,
    			CmsAttributeTableGenerator	signedAttrGen,
    			CmsAttributeTableGenerator	unsignedAttrGen)
    		{
    			signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(subjectKeyID),
    				digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
    		}
    
        #region AddSigner for AsymmetricKeyParameter
    
        /**
        * add a signer - no attributes other than the default ones will be
        * provided here.
    		*
    		* @param key signing key to use
    		* @param cert certificate containing corresponding public key
    		* @param digestOID digest algorithm OID
        */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string digestOID)
        {
          AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
         * provided here.
         *
         * @param key signing key to use
         * @param cert certificate containing corresponding public key
         * @param encryptionOID digest encryption algorithm OID
         * @param digestOID digest algorithm OID
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string encryptionOID,
          string digestOID)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert), digestOID, encryptionOID,
            new DefaultSignedAttributeTableGenerator(), null, null));
        }
    
        /**
         * add a signer - no attributes other than the default ones will be
         * provided here.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string digestOID)
        {
          AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
         * provided here.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string encryptionOID,
          string digestOID)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
            digestOID, encryptionOID,
            new DefaultSignedAttributeTableGenerator(), null, null));
        }
    
        /**
        * add a signer with extra signed/unsigned attributes.
    		*
    		* @param key signing key to use
    		* @param cert certificate containing corresponding public key
    		* @param digestOID digest algorithm OID
    		* @param signedAttr table of attributes to be included in signature
    		* @param unsignedAttr table of attributes to be included as unsigned
        */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string digestOID,
          Asn1.Cms.AttributeTable signedAttr,
          Asn1.Cms.AttributeTable unsignedAttr)
        {
          AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
            signedAttr, unsignedAttr);
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
         *
         * @param key signing key to use
         * @param cert certificate containing corresponding public key
         * @param encryptionOID digest encryption algorithm OID
         * @param digestOID digest algorithm OID
         * @param signedAttr table of attributes to be included in signature
         * @param unsignedAttr table of attributes to be included as unsigned
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string encryptionOID,
          string digestOID,
          Asn1.Cms.AttributeTable signedAttr,
          Asn1.Cms.AttributeTable unsignedAttr)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
            digestOID, encryptionOID,
            new DefaultSignedAttributeTableGenerator(signedAttr),
            new SimpleAttributeTableGenerator(unsignedAttr),
            signedAttr));
        }
    
        /**
         * add a signer with extra signed/unsigned attributes.
         *
         * @param key signing key to use
         * @param subjectKeyID subjectKeyID of corresponding public key
         * @param digestOID digest algorithm OID
         * @param signedAttr table of attributes to be included in signature
         * @param unsignedAttr table of attributes to be included as unsigned
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string digestOID,
          Asn1.Cms.AttributeTable signedAttr,
          Asn1.Cms.AttributeTable unsignedAttr)
        {
          AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
            new DefaultSignedAttributeTableGenerator(signedAttr),
            new SimpleAttributeTableGenerator(unsignedAttr));
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
         *
         * @param key signing key to use
         * @param subjectKeyID subjectKeyID of corresponding public key
         * @param encryptionOID digest encryption algorithm OID
         * @param digestOID digest algorithm OID
         * @param signedAttr table of attributes to be included in signature
         * @param unsignedAttr table of attributes to be included as unsigned
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string encryptionOID,
          string digestOID,
          Asn1.Cms.AttributeTable signedAttr,
          Asn1.Cms.AttributeTable unsignedAttr)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
            digestOID, encryptionOID,
            new DefaultSignedAttributeTableGenerator(signedAttr),
            new SimpleAttributeTableGenerator(unsignedAttr),
            signedAttr));
        }
    
        /**
         * add a signer with extra signed/unsigned attributes based on generators.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string digestOID,
          CmsAttributeTableGenerator signedAttrGen,
          CmsAttributeTableGenerator unsignedAttrGen)
        {
          AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
            signedAttrGen, unsignedAttrGen);
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string encryptionOID,
          string digestOID,
          CmsAttributeTableGenerator signedAttrGen,
          CmsAttributeTableGenerator unsignedAttrGen)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
            digestOID, encryptionOID,
            signedAttrGen, unsignedAttrGen, null));
        }
    
        /**
         * add a signer with extra signed/unsigned attributes based on generators.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string digestOID,
          CmsAttributeTableGenerator signedAttrGen,
          CmsAttributeTableGenerator unsignedAttrGen)
        {
          AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
            signedAttrGen, unsignedAttrGen);
        }
    
        /**
         * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string encryptionOID,
          string digestOID,
          CmsAttributeTableGenerator signedAttrGen,
          CmsAttributeTableGenerator unsignedAttrGen)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
            digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
        }
    
        #endregion
    
        protected string GetEncOid(
          NetCrypto.RSACryptoServiceProvider crProv,
          string digestOID)
        {
          string encOID = null;
    
          if (crProv is NetCrypto.RSACryptoServiceProvider)
          {
            if ((crProv).PublicOnly)
              throw new ArgumentException("Expected RSA private key");
    
            encOID = EncryptionRsa;
          }
          /*else if (key is DsaPrivateKeyParameters)
          {
            if (!digestOID.Equals(DigestSha1))
              throw new ArgumentException("can't mix DSA with anything but SHA1");
    
            encOID = EncryptionDsa;
          }
          else if (key is ECPrivateKeyParameters)
          {
            ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
            string algName = ecPrivKey.AlgorithmName;
    
            if (algName == "ECGOST3410")
            {
              encOID = EncryptionECGost3410;
            }
            else
            {
              // TO DO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
              encOID = (string)ecAlgorithms[digestOID];
    
              if (encOID == null)
                throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
            }
          }
          else if (key is Gost3410PrivateKeyParameters)
          {
            encOID = EncryptionGost3410;
          }
          else
          {
            throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
          }*/
    
          return encOID;
        }
    
    
    		/**
        * generate a signed object that for a CMS Signed Data object
        */
        public CmsSignedData Generate(
          CmsProcessable content)
        {
          return Generate(content, false);
        }
    
        /**
        * generate a signed object that for a CMS Signed Data
        * object - if encapsulate is true a copy
        * of the message will be included in the signature. The content type
        * is set according to the OID represented by the string signedContentType.
        */
        public CmsSignedData Generate(
          string			signedContentType,
          CmsProcessable	content,
          bool			encapsulate)
        {
          Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
          Asn1EncodableVector signerInfos = new Asn1EncodableVector();
    
    			_digests.Clear(); // clear the current preserved digest state
    
    			//
          // add the precalculated SignerInfo objects.
          //
          foreach (SignerInformation signer in _signers)
          {
    				digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
    				signerInfos.Add(signer.ToSignerInfo());
          }
    
    			//
          // add the SignerInfo objects
          //
    			bool isCounterSignature = (signedContentType == null);
    
    			DerObjectIdentifier contentTypeOID = isCounterSignature
    				?	CmsObjectIdentifiers.Data
    				:	new DerObjectIdentifier(signedContentType);
    
    			foreach (SignerInf signer in signerInfs)
          {
    				try
            {
    					digestAlgs.Add(signer.DigestAlgorithmID);
    					signerInfos.Add(signer.ToSignerInfo(contentTypeOID, content, rand, isCounterSignature));
    				}
            catch (IOException e)
            {
              throw new CmsException("encoding error.", e);
            }
            catch (InvalidKeyException e)
            {
              throw new CmsException("key inappropriate for signature.", e);
            }
            catch (SignatureException e)
            {
              throw new CmsException("error creating signature.", e);
            }
            catch (CertificateEncodingException e)
            {
              throw new CmsException("error creating sid.", e);
            }
          }
    
    			Asn1Set certificates = null;
    
    			if (_certs.Count != 0)
    			{
    				certificates = CmsUtilities.CreateBerSetFromList(_certs);
    			}
    
    			Asn1Set certrevlist = null;
    
    			if (_crls.Count != 0)
    			{
    				certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
    			}
    
    			Asn1OctetString octs = null;
    			if (encapsulate)
          {
            MemoryStream bOut = new MemoryStream();
    				if (content != null)
    				{
    	        try
    	        {
    	          content.Write(bOut);
    	        }
    	        catch (IOException e)
    	        {
    	          throw new CmsException("encapsulation error.", e);
    	        }
    				}
    				octs = new BerOctetString(bOut.ToArray());
          }
    
    			ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
    
          SignedData sd = new SignedData(
            new DerSet(digestAlgs),
            encInfo,
            certificates,
            certrevlist,
            new DerSet(signerInfos));
    
          ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);
    
          return new CmsSignedData(content, contentInfo);
        }
    
        /**
        * generate a signed object that for a CMS Signed Data
        * object - if encapsulate is true a copy
        * of the message will be included in the signature with the
        * default content type "data".
        */
        public CmsSignedData Generate(
          CmsProcessable	content,
          bool			encapsulate)
        {
          return this.Generate(Data, content, encapsulate);
        }
    
    		/**
    		* generate a set of one or more SignerInformation objects representing counter signatures on
    		* the passed in SignerInformation object.
    		*
    		* @param signer the signer to be countersigned
    		* @param sigProvider the provider to be used for counter signing.
    		* @return a store containing the signers.
    		*/
    		public SignerInformationStore GenerateCounterSigners(
    			SignerInformation signer)
    		{
    			return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
    		}
    
        public static bool arrAreEquals(byte[] a, byte[] b)
        {
          bool res = true;
    
          if (a.Length != b.Length) return false;
    
          for (int i = 0; i < a.Length; i++)
          {
            if (a[i] != b[i])
            {
              return false;
            }
          }
    
          return res;
        }
    
      }
    }

    e nella classe inserire un AddSigner override che ho nominato myAddSigner

    public void MyAddSigner(
    		NetCrypto.RSACryptoServiceProvider crProv,
    		X509Certificate cert,
    		string encryptionOID,
    		string digestOID,
    		Asn1.Cms.AttributeTable signedAttr,
            Asn1.Cms.AttributeTable unsignedAttr)
    		{
    			signerInfs.Add(new SignerInf(this, crProv, null,   GetSignerIdentifier(cert), digestOID, encryptionOID,
    	new DefaultSignedAttributeTableGenerator(signedAttr), new SimpleAttributeTableGenerator(unsignedAttr), null));
    
    		}
    

    A questo punto ricompilare la dll bouncy e referenziarla nel progetto che state facendo.

    Un grazie in anticipo per chi mi può aiutare con le questioni citate all'inizio del post

    Ciao

    Piercarlo

    • Proposto come risposta Irina Turcu mercoledì 27 luglio 2011 08:08
    • Contrassegnato come risposta Irina Turcu giovedì 4 agosto 2011 16:25
    sabato 23 luglio 2011 18:01
  • Ciao Piero

    Il tuo codice non funziona poichè non passi tutti i parametri che servono al csp questo codice funziona invece:

            //MI PREPARO IL PIN
            string PIN = "11111111";
            // Instantiate the secure string.
            SecureString SecurePIN = new SecureString();
            // Use the AppendChar method to add each char value to the secure string.
            foreach (char ch in PIN)
              SecurePIN.AppendChar(ch);
            var rsa = (RSACryptoServiceProvider)cert.PrivateKey;
            string ContinerName = rsa.CspKeyContainerInfo.KeyContainerName;
            string CspName = rsa.CspKeyContainerInfo.ProviderName;
            int CspType = rsa.CspKeyContainerInfo.ProviderType;
            //MI SETTO I PARAMETRI DEL CSP
            CspParameters csp = new CspParameters(CspType,CspName, ContinerName, new System.Security.AccessControl.CryptoKeySecurity(), SecurePIN);
            // INIZIALIZZO IL nuovo CSP con la password
            RSACryptoServiceProvider CSP = new RSACryptoServiceProvider(csp);
            //passo tutto a bouncyCastle
    
    

    Adesso non mi rimane altro che risolvere il problema delle due card con i due lettori o più inseriti contmporaneamente sullo stesso pc

    Sequalcuno riesce a darmi una mano ne sarei felice

    Ciao a Tutti

    Piercarlo

    • Proposto come risposta Irina Turcu mercoledì 27 luglio 2011 08:09
    • Contrassegnato come risposta Irina Turcu giovedì 4 agosto 2011 16:25
    lunedì 25 luglio 2011 15:27

Tutte le risposte

  • Ciao Piercarlo

     

    Ti ricordo che questo è un forum localizzato in italiano, quindi puoi parlare in italiano.... :)

     

    Per quel che so io non è supportato del tutto il CADES-BES da .NET.

    Nel blog degli SDKppiani di WS sembrano dire proprio questo

    http://blogs.msdn.com/b/winsdk/archive/2010/08/06/compliance-of-net-security-libraries-about-verifying-a-cms-advanced-electronic-signatures-cades-message.aspx

    Stessa cosa x altri ke ci hanno sbattuto la testa

    http://social.msdn.microsoft.com/Forums/it-IT/visualcsharpit/thread/d4f4c062-eeba-4e77-86ae-37c66b645a81/

     

    Forse Raf (Rialdi) puo darti una mano perchè dovrebbe essere il suo campo, a meno ke non vuoi scriverti il tuo provider CADES a mano ke nel caso spero tanto tu posti online :)

    Bye

    Anto


    Antonio Esposito
    MCT, MCPD, MCTS, MCP
    http://dotnetlombardia.org
    martedì 12 luglio 2011 09:08
    Postatore
  • Grazie

    Avevo visto anch'io i post che mi hai mandato, ma speravo tanto che ci fosse un'alternativa con .net.

    Sicuramente non scriverò il provider CADES anche perchè non so da che parte cominciare.

    Comunque sembra che si possa utilizzare le API di BouncyCastle per risolvere.

    Allora la nuova domanda è

    Esiste qualcuno che si è già sbattuto con BouncyCastle c# e che mi può dare delle indicazioni ?

    Un grazie in Anticipo

    Piercarlo

    martedì 12 luglio 2011 09:17
  • Ciao Piercarlo,

    Il Bouncy Castle lo puoi scaricare da qui: The Legion of the Bouncy Castle. Trovi dei esempi nella pagina di Documentazione Bouncy Castle.

    Per un esempio .NET ti rimando a una discussione già aperta qualche tempo fa nel forum tedesco. Se lo metto nel traduttore, cambia la sorgente, quindi l’ho collegato in tedesco, tanto il codice spiega se stesso:

    Eccezione quando si importa un ECDSA PKCS # 12 container (tedesco)

    Spero lo trovassi utile.

     

    Grazie in anticipo di tenerci aggiornati sul tuo percorso,

    Irina


    Questo contenuto è distribuito “as is” e non implica alcuna responsabilità da parte di Microsoft. L'azienda offre questo servizio gratuitamente, allo scopo di aiutare gli utenti e farli aumentare la conoscenza sui prodotti e le tecnologie Microsoft.

    LinkedIn

    martedì 19 luglio 2011 15:57
  • Ti ringrazio per la segnalazione, ma non mi è molto di aiuto poichè descrive una firma pkcs#12 cioè con il certificato su file e non su SmartCard e poi manca tutta la parte del CADES-BES.

    In ogni caso grazie

    Piercarlo

    mercoledì 20 luglio 2011 07:14
  • Eccomi di Nuovo:

    Allora ho risolto qualcosa ed ho ancora qualche domanda

    Sono riuscito a firmare con le dll bouncy castle con le specifiche CADES-BES senza alcun problema (di seguito posto il codice per chi ne abbia bisogno)

    Ho solo bisogno del seguente aiuto:

    Allora :

    Vorrei passare al CSP la password programmaticamente.

    Con questo sistema se ho più certificati di firma con più chiavette inserite nel computer mi viene sempre presa la prima chiavetta USB con conseguente errore se non contiene il certificato giusto, vorrei essere in grado di selezionarle in base al certificato in esse contenuto.

    Di seguito il codice che ho usato:

    Per Selezionare il certificato e scrivere il file:

        private void button1_Click(object sender, EventArgs e)
        {
          try
          {
            //mi seleziono il certificato
            X509Store st = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            st.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection col = st.Certificates;
            X509Certificate2 card = null;
            X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(col, "Certificates", "Select one to sign", X509SelectionFlag.SingleSelection);
            if (sel.Count > 0)
            {
              X509Certificate2Enumerator en = sel.GetEnumerator();
              en.MoveNext();
              card = en.Current;
            }
            st.Close();
    
            if (card != null)
            {
              openFileDialog1.ShowDialog();
              if (!string.IsNullOrEmpty(openFileDialog1.FileName))
              {
                string Res = "";
                string NomeFile = openFileDialog1.FileName;
                byte[] Firmato = FirmaFileBouncy(NomeFile, card, out Res);
                if (string.IsNullOrEmpty(Res))
                {
                  File.WriteAllBytes(NomeFile + ".p7m", Firmato);
                  MessageBox.Show("Messaggio Firmato Con Successo");
                }
                else
                {
                  throw new Exception(Res);
                }
              }
            }
          }
          catch (Exception ex)
          {
            MessageBox.Show(ex.ToString());
          }
        }
    

    per firmare il file con le crypto bouncy

        public byte[] FirmaFileBouncy(String NomeFile, X509Certificate2 cert, out string RisFirma)
        {
          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();
    
            var 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 = new FileInfo(NomeFile);
            CmsProcessableFile file = new CmsProcessableFile(File);
            CmsSignedData Firmato = cms.Generate(file, true);
            byte[] Encoded = Firmato.GetEncoded();
            RisFirma = "";
            return Encoded;
          }
          catch (Exception ex)
          {
            RisFirma = ex.ToString();
            return null;
          }
        }
    

    Per farequesto bisogna scaricare il sorgente dal sito di bouncyCasle "bccrypto-net-1.7-src-ext.zip"

    inserire la seguente classe:

    using System;
    using System.Collections;
    using System.IO;
    
    using Org.BouncyCastle.Asn1;
    using Asn1 = Org.BouncyCastle.Asn1;
    using Org.BouncyCastle.Asn1.Cms;
    using Org.BouncyCastle.Asn1.X509;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.Security.Certificates;
    using Org.BouncyCastle.X509;
    using Org.BouncyCastle.Cms;
    using NetCrypto = System.Security.Cryptography;
    
    namespace CryptoUpgNet.NonExportablePK
    {
      public class CmsSignedDataGenWithRsaCsp
        : CmsSignedGenerator
      {
    		private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
    
    		private readonly ArrayList signerInfs = new ArrayList();
    
    		private class SignerInf
        {
          private readonly CmsSignedGenerator outer;
    
    			private readonly AsymmetricKeyParameter		key;
          private readonly NetCrypto.RSACryptoServiceProvider krProv;
    			private readonly SignerIdentifier			signerIdentifier;
    			private readonly string						digestOID;
    			private readonly string						encOID;
    			private readonly CmsAttributeTableGenerator	sAttr;
    			private readonly CmsAttributeTableGenerator	unsAttr;
    			private readonly Asn1.Cms.AttributeTable	baseSignedTable;
    
          /// <summary>
          /// Signer is received with crypto provider or pr. key (if the crypto provider == null)
          /// </summary>
          /// <param name="krProv">Crypto provider. if null than use key</param>
          /// <param name="key">Private key</param>
    			internal SignerInf(
            CmsSignedGenerator			outer,
            NetCrypto.RSACryptoServiceProvider krProv,
    	      AsymmetricKeyParameter		key,
    	      SignerIdentifier			signerIdentifier,
    	      string						digestOID,
    	      string						encOID,
    	      CmsAttributeTableGenerator	sAttr,
    	      CmsAttributeTableGenerator	unsAttr,
    	      Asn1.Cms.AttributeTable		baseSignedTable)
    	    {
            this.outer = outer;
            this.key = key;
            this.krProv = krProv;
            this.signerIdentifier = signerIdentifier;
            this.digestOID = digestOID;
            this.encOID = encOID;
    	      this.sAttr = sAttr;
    	      this.unsAttr = unsAttr;
    	      this.baseSignedTable = baseSignedTable;
          }
    
    			internal AlgorithmIdentifier DigestAlgorithmID
    			{
    				get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
    			}
    
    			internal CmsAttributeTableGenerator SignedAttributes
          {
    				get { return sAttr; }
          }
    
          internal CmsAttributeTableGenerator UnsignedAttributes
          {
    				get { return unsAttr; }
          }
    
    			internal SignerInfo ToSignerInfo(
            DerObjectIdentifier	contentType,
            CmsProcessable		content,
    				SecureRandom		random,
    				bool				isCounterSignature)
          {
            AlgorithmIdentifier digAlgId = DigestAlgorithmID;
            string digestName = Helper.GetDigestAlgName(digestOID);
            
            IDigest dig = Helper.GetDigestInstance(digestName);
    
            string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
            //ISigner sig moved there where used
    
            // TODO Optimise the case where more than one signer with same digest
            if (content != null)
            {
              content.Write(new DigOutputStream(dig));
            }
    
            byte[] hash = DigestUtilities.DoFinal(dig);
            outer._digests.Add(digestOID, hash.Clone());
    
            Asn1Set signedAttr = null;
            byte[] tmp;
            if (sAttr != null)
            {
              IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
    
              //					Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
              Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters);
    
              if (isCounterSignature)
              {
                Hashtable tmpSigned = signed.ToHashtable();
                tmpSigned.Remove(CmsAttributes.ContentType);
                signed = new Asn1.Cms.AttributeTable(tmpSigned);
              }
    
              // TODO Validate proposed signed attributes
    
              signedAttr = outer.GetAttributeSet(signed);
    
              // sig must be composed from the DER encoding.
              tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
            }
            else
            {
              // TODO Use raw signature of the hash value instead
              MemoryStream bOut = new MemoryStream();
              if (content != null)
              {
                content.Write(bOut);
              }
              tmp = bOut.ToArray();
            }
    
            byte[] sigBytes = null;
            if (krProv != null)
            {
              /*
              sig.GenerateSignature() supports the following hashes:
              MD2
              MD4
              MD5
              SHA1
              SHA224
              SHA256
              SHA384
              SHA512
              RIPEMD128
              RIPEMD160
              RIPEMD256
              *
              krProv.SignData(tmp, digestName) supports the following digestName:
              MD5
              SHA1
              SHA256
              SHA384
              SHA512
              */
    
              //sigBytes = krProv.SignData(tmp, digestName);
    
              IDigest digProv = Helper.GetDigestInstance(digestName);
              digProv.BlockUpdate(tmp, 0, tmp.Length);
              byte[] hashProv = new byte[digProv.GetDigestSize()];
              digProv.DoFinal(hashProv, 0);
    
              sigBytes = krProv.SignHash(hashProv, digestOID);
    
            }
            else
            {
              ISigner sig = Helper.GetSignatureInstance(signatureName);//was moved
              sig.Init(true, new ParametersWithRandom(key, random));
              sig.BlockUpdate(tmp, 0, tmp.Length);
              sigBytes = sig.GenerateSignature();
            }
            
            Asn1Set unsignedAttr = null;
            if (unsAttr != null)
            {
              IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
              baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();
    
              //					Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
              Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);
    
              // TODO Validate proposed unsigned attributes
    
              unsignedAttr = outer.GetAttributeSet(unsigned);
            }
    
            // TODO [RSAPSS] Need the ability to specify non-default parameters
            Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
            AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
              new DerObjectIdentifier(encOID), sigX509Parameters);
    
            return new SignerInfo(signerIdentifier, digAlgId,
              signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
          }
        }
    
    		public CmsSignedDataGenWithRsaCsp()
        {
        }
    
    		/// <summary>Constructor allowing specific source of randomness</summary>
    		/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
    		public CmsSignedDataGenWithRsaCsp(
    			SecureRandom rand)
    			: base(rand)
    		{
    		}
    
        /// <summary>
        /// add a signer - no attributes other than the default ones will be provided here для RSACryptoServiceProvider
        /// </summary>
        /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
        /// <param name="cert">cert certificate containing corresponding public key</param>
        /// <param name="digestOID">digestOID digest algorithm OID</param>
        public void AddSigner(
          NetCrypto.RSACryptoServiceProvider	crProv,
          X509Certificate			cert,
          string					digestOID)
        {
        	AddSigner(crProv, cert, GetEncOid(crProv, digestOID), digestOID);
    		}
    
    		/// <summary>
    		/// add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be provided here.
    		/// </summary>
        /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
        /// <param name="cert">certificate containing corresponding public key</param>
        /// <param name="encryptionOID">digest encryption algorithm OID</param>
        /// <param name="digestOID">digest algorithm OID</param>
    		public void AddSigner(
          NetCrypto.RSACryptoServiceProvider crProv,
    			X509Certificate			cert,
    			string					encryptionOID,
    			string					digestOID)
    		{
    			signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(cert), digestOID, encryptionOID,
    				new DefaultSignedAttributeTableGenerator(), null, null));
    		}
    
    		/// <summary>
        /// add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators
    		/// </summary>
    		public void AddSigner(
          NetCrypto.RSACryptoServiceProvider crProv,
    			byte[]						subjectKeyID,
    			string						encryptionOID,
    			string						digestOID,
    			CmsAttributeTableGenerator	signedAttrGen,
    			CmsAttributeTableGenerator	unsignedAttrGen)
    		{
    			signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(subjectKeyID),
    				digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
    		}
    
        #region AddSigner for AsymmetricKeyParameter
    
        /**
        * add a signer - no attributes other than the default ones will be
        * provided here.
    		*
    		* @param key signing key to use
    		* @param cert certificate containing corresponding public key
    		* @param digestOID digest algorithm OID
        */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string digestOID)
        {
          AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
         * provided here.
         *
         * @param key signing key to use
         * @param cert certificate containing corresponding public key
         * @param encryptionOID digest encryption algorithm OID
         * @param digestOID digest algorithm OID
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string encryptionOID,
          string digestOID)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert), digestOID, encryptionOID,
            new DefaultSignedAttributeTableGenerator(), null, null));
        }
    
        /**
         * add a signer - no attributes other than the default ones will be
         * provided here.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string digestOID)
        {
          AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
         * provided here.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string encryptionOID,
          string digestOID)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
            digestOID, encryptionOID,
            new DefaultSignedAttributeTableGenerator(), null, null));
        }
    
        /**
        * add a signer with extra signed/unsigned attributes.
    		*
    		* @param key signing key to use
    		* @param cert certificate containing corresponding public key
    		* @param digestOID digest algorithm OID
    		* @param signedAttr table of attributes to be included in signature
    		* @param unsignedAttr table of attributes to be included as unsigned
        */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string digestOID,
          Asn1.Cms.AttributeTable signedAttr,
          Asn1.Cms.AttributeTable unsignedAttr)
        {
          AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
            signedAttr, unsignedAttr);
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
         *
         * @param key signing key to use
         * @param cert certificate containing corresponding public key
         * @param encryptionOID digest encryption algorithm OID
         * @param digestOID digest algorithm OID
         * @param signedAttr table of attributes to be included in signature
         * @param unsignedAttr table of attributes to be included as unsigned
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string encryptionOID,
          string digestOID,
          Asn1.Cms.AttributeTable signedAttr,
          Asn1.Cms.AttributeTable unsignedAttr)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
            digestOID, encryptionOID,
            new DefaultSignedAttributeTableGenerator(signedAttr),
            new SimpleAttributeTableGenerator(unsignedAttr),
            signedAttr));
        }
    
        /**
         * add a signer with extra signed/unsigned attributes.
         *
         * @param key signing key to use
         * @param subjectKeyID subjectKeyID of corresponding public key
         * @param digestOID digest algorithm OID
         * @param signedAttr table of attributes to be included in signature
         * @param unsignedAttr table of attributes to be included as unsigned
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string digestOID,
          Asn1.Cms.AttributeTable signedAttr,
          Asn1.Cms.AttributeTable unsignedAttr)
        {
          AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
            new DefaultSignedAttributeTableGenerator(signedAttr),
            new SimpleAttributeTableGenerator(unsignedAttr));
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
         *
         * @param key signing key to use
         * @param subjectKeyID subjectKeyID of corresponding public key
         * @param encryptionOID digest encryption algorithm OID
         * @param digestOID digest algorithm OID
         * @param signedAttr table of attributes to be included in signature
         * @param unsignedAttr table of attributes to be included as unsigned
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string encryptionOID,
          string digestOID,
          Asn1.Cms.AttributeTable signedAttr,
          Asn1.Cms.AttributeTable unsignedAttr)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
            digestOID, encryptionOID,
            new DefaultSignedAttributeTableGenerator(signedAttr),
            new SimpleAttributeTableGenerator(unsignedAttr),
            signedAttr));
        }
    
        /**
         * add a signer with extra signed/unsigned attributes based on generators.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string digestOID,
          CmsAttributeTableGenerator signedAttrGen,
          CmsAttributeTableGenerator unsignedAttrGen)
        {
          AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
            signedAttrGen, unsignedAttrGen);
        }
    
        /**
         * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          X509Certificate cert,
          string encryptionOID,
          string digestOID,
          CmsAttributeTableGenerator signedAttrGen,
          CmsAttributeTableGenerator unsignedAttrGen)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
            digestOID, encryptionOID,
            signedAttrGen, unsignedAttrGen, null));
        }
    
        /**
         * add a signer with extra signed/unsigned attributes based on generators.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string digestOID,
          CmsAttributeTableGenerator signedAttrGen,
          CmsAttributeTableGenerator unsignedAttrGen)
        {
          AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
            signedAttrGen, unsignedAttrGen);
        }
    
        /**
         * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
         */
        public void AddSigner(
          AsymmetricKeyParameter privateKey,
          byte[] subjectKeyID,
          string encryptionOID,
          string digestOID,
          CmsAttributeTableGenerator signedAttrGen,
          CmsAttributeTableGenerator unsignedAttrGen)
        {
          signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
            digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
        }
    
        #endregion
    
        protected string GetEncOid(
          NetCrypto.RSACryptoServiceProvider crProv,
          string digestOID)
        {
          string encOID = null;
    
          if (crProv is NetCrypto.RSACryptoServiceProvider)
          {
            if ((crProv).PublicOnly)
              throw new ArgumentException("Expected RSA private key");
    
            encOID = EncryptionRsa;
          }
          /*else if (key is DsaPrivateKeyParameters)
          {
            if (!digestOID.Equals(DigestSha1))
              throw new ArgumentException("can't mix DSA with anything but SHA1");
    
            encOID = EncryptionDsa;
          }
          else if (key is ECPrivateKeyParameters)
          {
            ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
            string algName = ecPrivKey.AlgorithmName;
    
            if (algName == "ECGOST3410")
            {
              encOID = EncryptionECGost3410;
            }
            else
            {
              // TO DO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
              encOID = (string)ecAlgorithms[digestOID];
    
              if (encOID == null)
                throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
            }
          }
          else if (key is Gost3410PrivateKeyParameters)
          {
            encOID = EncryptionGost3410;
          }
          else
          {
            throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
          }*/
    
          return encOID;
        }
    
    
    		/**
        * generate a signed object that for a CMS Signed Data object
        */
        public CmsSignedData Generate(
          CmsProcessable content)
        {
          return Generate(content, false);
        }
    
        /**
        * generate a signed object that for a CMS Signed Data
        * object - if encapsulate is true a copy
        * of the message will be included in the signature. The content type
        * is set according to the OID represented by the string signedContentType.
        */
        public CmsSignedData Generate(
          string			signedContentType,
          CmsProcessable	content,
          bool			encapsulate)
        {
          Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
          Asn1EncodableVector signerInfos = new Asn1EncodableVector();
    
    			_digests.Clear(); // clear the current preserved digest state
    
    			//
          // add the precalculated SignerInfo objects.
          //
          foreach (SignerInformation signer in _signers)
          {
    				digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
    				signerInfos.Add(signer.ToSignerInfo());
          }
    
    			//
          // add the SignerInfo objects
          //
    			bool isCounterSignature = (signedContentType == null);
    
    			DerObjectIdentifier contentTypeOID = isCounterSignature
    				?	CmsObjectIdentifiers.Data
    				:	new DerObjectIdentifier(signedContentType);
    
    			foreach (SignerInf signer in signerInfs)
          {
    				try
            {
    					digestAlgs.Add(signer.DigestAlgorithmID);
    					signerInfos.Add(signer.ToSignerInfo(contentTypeOID, content, rand, isCounterSignature));
    				}
            catch (IOException e)
            {
              throw new CmsException("encoding error.", e);
            }
            catch (InvalidKeyException e)
            {
              throw new CmsException("key inappropriate for signature.", e);
            }
            catch (SignatureException e)
            {
              throw new CmsException("error creating signature.", e);
            }
            catch (CertificateEncodingException e)
            {
              throw new CmsException("error creating sid.", e);
            }
          }
    
    			Asn1Set certificates = null;
    
    			if (_certs.Count != 0)
    			{
    				certificates = CmsUtilities.CreateBerSetFromList(_certs);
    			}
    
    			Asn1Set certrevlist = null;
    
    			if (_crls.Count != 0)
    			{
    				certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
    			}
    
    			Asn1OctetString octs = null;
    			if (encapsulate)
          {
            MemoryStream bOut = new MemoryStream();
    				if (content != null)
    				{
    	        try
    	        {
    	          content.Write(bOut);
    	        }
    	        catch (IOException e)
    	        {
    	          throw new CmsException("encapsulation error.", e);
    	        }
    				}
    				octs = new BerOctetString(bOut.ToArray());
          }
    
    			ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
    
          SignedData sd = new SignedData(
            new DerSet(digestAlgs),
            encInfo,
            certificates,
            certrevlist,
            new DerSet(signerInfos));
    
          ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);
    
          return new CmsSignedData(content, contentInfo);
        }
    
        /**
        * generate a signed object that for a CMS Signed Data
        * object - if encapsulate is true a copy
        * of the message will be included in the signature with the
        * default content type "data".
        */
        public CmsSignedData Generate(
          CmsProcessable	content,
          bool			encapsulate)
        {
          return this.Generate(Data, content, encapsulate);
        }
    
    		/**
    		* generate a set of one or more SignerInformation objects representing counter signatures on
    		* the passed in SignerInformation object.
    		*
    		* @param signer the signer to be countersigned
    		* @param sigProvider the provider to be used for counter signing.
    		* @return a store containing the signers.
    		*/
    		public SignerInformationStore GenerateCounterSigners(
    			SignerInformation signer)
    		{
    			return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
    		}
    
        public static bool arrAreEquals(byte[] a, byte[] b)
        {
          bool res = true;
    
          if (a.Length != b.Length) return false;
    
          for (int i = 0; i < a.Length; i++)
          {
            if (a[i] != b[i])
            {
              return false;
            }
          }
    
          return res;
        }
    
      }
    }

    e nella classe inserire un AddSigner override che ho nominato myAddSigner

    public void MyAddSigner(
    		NetCrypto.RSACryptoServiceProvider crProv,
    		X509Certificate cert,
    		string encryptionOID,
    		string digestOID,
    		Asn1.Cms.AttributeTable signedAttr,
            Asn1.Cms.AttributeTable unsignedAttr)
    		{
    			signerInfs.Add(new SignerInf(this, crProv, null,   GetSignerIdentifier(cert), digestOID, encryptionOID,
    	new DefaultSignedAttributeTableGenerator(signedAttr), new SimpleAttributeTableGenerator(unsignedAttr), null));
    
    		}
    

    A questo punto ricompilare la dll bouncy e referenziarla nel progetto che state facendo.

    Un grazie in anticipo per chi mi può aiutare con le questioni citate all'inizio del post

    Ciao

    Piercarlo

    • Proposto come risposta Irina Turcu mercoledì 27 luglio 2011 08:08
    • Contrassegnato come risposta Irina Turcu giovedì 4 agosto 2011 16:25
    sabato 23 luglio 2011 18:01
  • Ciao Piercarlo,

    se ho ben capito vorresti passare la password della smartcard in maniera automatica...cioè magari rendendola costante da codice. Se è questo quello che vuoi...ti dico che anch'io mi sono cimentato per del tempo e con questo codice...

    RSACryptoServiceProvider rsa = (System.Security.Cryptography.RSACryptoServiceProvider)windowscertificate.PrivateKey;
    String cspprovider = (rsa.CspKeyContainerInfo.ProviderName);
    CspParameters csp = new CspParameters(GetProviderType(windowscertificate), cspprovider);
    csp.Flags = CspProviderFlags.UseDefaultKeyContainer;

    //password do token                  

    System.Security.SecureString pwd = new System.Security.SecureString();
    pwd.AppendChar('1'); pwd.AppendChar('2'); pwd.AppendChar('3'); pwd.AppendChar('4'); pwd.AppendChar('5'); pwd.AppendChar('6'); pwd.AppendChar('7'); pwd.AppendChar('8');
    csp.KeyPassword = pwd;
    csp.KeyNumber = (int)KeyNumber.Signature;

                       
    rsa = new RSACryptoServiceProvider(csp);
    byte[] contentinfo = rsa.SignData(data, "SHA256");

     

    ...sono riuscito a firmare senza inserire il pin perchè costante da codice. Ho avuto però qualche problema di verifica della firma.

    Provalo e fammi sapere se hai qualche problema.

     

    Ciao.

     

    Piero

    lunedì 25 luglio 2011 07:38
  • Ciao Piero

    Il tuo codice non funziona poichè non passi tutti i parametri che servono al csp questo codice funziona invece:

            //MI PREPARO IL PIN
            string PIN = "11111111";
            // Instantiate the secure string.
            SecureString SecurePIN = new SecureString();
            // Use the AppendChar method to add each char value to the secure string.
            foreach (char ch in PIN)
              SecurePIN.AppendChar(ch);
            var rsa = (RSACryptoServiceProvider)cert.PrivateKey;
            string ContinerName = rsa.CspKeyContainerInfo.KeyContainerName;
            string CspName = rsa.CspKeyContainerInfo.ProviderName;
            int CspType = rsa.CspKeyContainerInfo.ProviderType;
            //MI SETTO I PARAMETRI DEL CSP
            CspParameters csp = new CspParameters(CspType,CspName, ContinerName, new System.Security.AccessControl.CryptoKeySecurity(), SecurePIN);
            // INIZIALIZZO IL nuovo CSP con la password
            RSACryptoServiceProvider CSP = new RSACryptoServiceProvider(csp);
            //passo tutto a bouncyCastle
    
    

    Adesso non mi rimane altro che risolvere il problema delle due card con i due lettori o più inseriti contmporaneamente sullo stesso pc

    Sequalcuno riesce a darmi una mano ne sarei felice

    Ciao a Tutti

    Piercarlo

    • Proposto come risposta Irina Turcu mercoledì 27 luglio 2011 08:09
    • Contrassegnato come risposta Irina Turcu giovedì 4 agosto 2011 16:25
    lunedì 25 luglio 2011 15:27
  • Ok è perfetto ora, grazie alla valorizzazione di quei parametri firmo e verifico correttamente.

    Sempre in riferimento alla gestione del pin volevo condividere questo codice (spero possa essere utile a qualcuno) che permette di svuotare il buffer che memorizza il temporaneamente il pin della smartcard dopo averlo inserito da tastiera.

    public bool ClearPINCache(RSACryptoServiceProvider key)
            {
                const uint PP_KEYEXCHANGE_PIN = 32;
                const uint PP_SIGNATURE_PIN = 33;
                bool bretval = false;

                IntPtr hProv = IntPtr.Zero;

                if (CryptAcquireContext(ref hProv, key.CspKeyContainerInfo.KeyContainerName,
                    key.CspKeyContainerInfo.ProviderName, (uint)key.CspKeyContainerInfo.ProviderType, 0))
                {
                    if ((CryptSetProvParam(hProv, PP_KEYEXCHANGE_PIN, IntPtr.Zero, 0) == true) &&
                        (CryptSetProvParam(hProv, PP_SIGNATURE_PIN, IntPtr.Zero, 0) == true))
                    {
                        bretval = true;
                    }
                }

                if (hProv != IntPtr.Zero)
                {
                    CryptReleaseContext(hProv, 0);
                    hProv = IntPtr.Zero;
                }

                return bretval;
            }

     

    Ciao

    martedì 26 luglio 2011 08:22
  • Ciao Piercarlo,

    Hai detto che:

    Adesso non mi rimane altro che risolvere il problema delle due card con i due lettori o più inseriti contmporaneamente sullo stesso pc

    Sequalcuno riesce a darmi una mano ne sarei felice

    Ciao a Tutti

    Piercarlo


    Siccome il problema esposto inizialmente è stato risolto, vorrei chiederti di aprire un nuovo thread dove fornirci più dettagli su quello che vuoi fare.


    Grazie in anticipo della tua collaborazione,

    Irina


    Questo contenuto è distribuito “as is” e non implica alcuna responsabilità da parte di Microsoft. L'azienda offre questo servizio gratuitamente, allo scopo di aiutare gli utenti e farli aumentare la conoscenza sui prodotti e le tecnologie Microsoft.

    LinkedIn

    mercoledì 27 luglio 2011 08:13
  • Ciao,

    esiste un modo per bloccare il sistema di  firma digitale multipla utilizzando la libreria BouncyCastle c#?
    In pratica il documento deve essere firmato una sola volta e non consentire la controfirma.

    Grazie

    Marco


    • Modificato m.denicola giovedì 16 aprile 2015 09:12
    giovedì 16 aprile 2015 09:11
  • Ciao Marco

    Non penso che con Bouncy si possa fare ma sicuramente in c# puoi farlo comodamente inserendo una variabile boleana del tipo del tipo "bool firmato" che setti a true una volta fatta la firma.

    Inserisci il codice per la firma dentro ad un if del genere:

    Dichiari la variabile

    bool firmato;

    ........codice

    If(!firmato)

    {

    "codice per firmare"

    firmato = true;

    }

    else

    {

    MsgBox("Il documeto é giá stato firmato !")

    }

    giovedì 16 aprile 2015 16:52
  • Grazie per la risposta,

    ci avevo pensato anche io.

    Intendevo un sistema di blocco firma riconosciuto anche dagli altri programmi tipo Dike, Firma Certa e via dicendo. 

    Chiedo questo perché non ho trovato nessun argomento sul numero di firme da apporre ad un documento . In pratica come faccio a dire che il documento una volta firmato non può essere  controfirmato?

    Marco

    venerdì 17 aprile 2015 08:14
  • Non puoi farlo e basta.

    Nei parametri tecnici della legislazione corrente non esiste il blocco delle firme e di conseguenza nessun programma lo prevede e di conseguenza lo implementa.

    Perció é una cosa che puoi fare a livello di programma (il tuo) ma che non puoi estendere a programmi esterni.

    Ciao

    Piercarlo

    venerdì 17 aprile 2015 11:24
  • Ciao Piercarlo,

    ho capito!

    Mi mancava il passaggio sulle regole delle firme.

    Come posso aggiungere una controfirma selezionando una delle firme già esistenti?

    Grazie mille!

    Marco


    • Modificato m.denicola lunedì 20 aprile 2015 12:59
    lunedì 20 aprile 2015 10:03
  • Buongiorno, 

    anche io ho la necessità di firmare massivamente dei documenti pdf tramite smart card.

    Pensavo di fare una procedura in vb appoggiandomi alle librerie  Bouncy Castel ma sto avendop problemi con i vecchi riferimenti e suggerimenti  che erano nei post precedenti.

    Avete realizzato qualcosa del genere ? 

    martedì 19 ottobre 2021 10:09
  • Ciao, io ho scritto questa classe "Firma" che firma più file .pdf secondo lo standard PADES-BES, anche con firma multipla. Ovviamente, chiede il PIN solo una volta. Puoi anche decidere se sovrascrivere o no il file originale. Utilizza la libreria ITextSharp, che puoi trovare nei pacchetti NuGet, e il riferimento a System.Security.dll, che puoi trovare sul tuo hard disk:  "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Security.dll".

    using System;
    using System.IO;
    using System.Security.Cryptography.X509Certificates;
    using iTextSharp.text.pdf;
    using iTextSharp.text.pdf.security;
    
    
    namespace FirmaDigitalePdf
    {
        class Program
        {
            public static void Main()
            {                        
                string[] tuttiFile = new string[] { @"d:\prova1.pdf", @"d:\prova2.pdf" };
                bool sovrascrivi = false;
                Firma.FirmaPdf(tuttiFile, sovrascrivi);
            }
        }    
        public static class Firma
        {
            public static string FirmaPdf(string nomeFile, bool overwrite)
            {
                return FirmaPdf(new string[] { nomeFile }, overwrite);
            }
            public static string FirmaPdf(string[] nomiFile, bool overwrite)
            {            
                //mette la firma PADES nei file .pdf
                //Funziona anche con più firme, una dopo l'altra. Tutte vengono riconosciute.
    
                try
                {
                    //sceglie il certificato dallo Store
                    X509Store st = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                    st.Open(OpenFlags.ReadOnly);
                    X509Certificate2Collection col = st.Certificates;                
                    X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(col, "Certificati", "Selezionane uno per firmare:", X509SelectionFlag.SingleSelection);
                    X509Certificate2 card = null;
                    if (sel.Count > 0)
                    {
                        X509Certificate2Enumerator en = sel.GetEnumerator();
                        en.MoveNext();
                        card = en.Current;
                    }
                    st.Close();                               
                    if (card == null)
                        return "Certificato non selezionato!";
                    if (DateTime.Now > card.NotAfter)
                        return "Certificato scaduto!";
    
                    X509Certificate2 certificate = card;
    
                    foreach (string nomeFile in nomiFile)
                    {
                        Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
                        Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(certificate.RawData) };
                        IExternalSignature externalSignature = new X509Certificate2Signature(certificate, DigestAlgorithms.SHA256);                                        
                        PdfReader pdfReader = new PdfReader(nomeFile);                    
                        string nomeFileFirmato = Path.GetDirectoryName(nomeFile) + "\\" + Path.GetFileNameWithoutExtension(nomeFile) + "-signed.pdf";
                        FileStream signedPdf = new FileStream(nomeFileFirmato, FileMode.Create);                    
                        PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0', null, true);     
                        //l'ultimo parametro "true" serve per fare l'append per le firme multiple
                        PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;                    
                        signatureAppearance.SignatureCreator = certificate.SubjectName.Name;
                        signatureAppearance.Reason = "";
                        signatureAppearance.Location = "";
                        signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;                    
    
                        //Per mettere la marca temporale (questa non è riconosciuta in Italia?):
                        //TSAClientBouncyCastle tsaClient = new TSAClientBouncyCastle("https://freetsa.org/tsr");
                        TSAClientBouncyCastle tsaClient = null;
                        
                        MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, tsaClient, 0, CryptoStandard.CADES);                    
                        //CryptoStandard.CADES serve per abilitare SHA-256 (= PAdES-BES).                    
                        if (overwrite == true)
                        {
                            File.Copy(nomeFileFirmato, nomeFile, true);
                            File.Delete(nomeFileFirmato);                         
                        }
                    }
                    return "";
                }
                catch (Exception e)
                {
                    return e.Message;
                }           
            }
        }
    }



    • Modificato fabiocaruso martedì 19 ottobre 2021 18:36
    martedì 19 ottobre 2021 18:25
  • Grazie Fabio,

    sto guardando il codice.

    Che versione stai usando dell' ITextSharp ?


    mercoledì 20 ottobre 2021 09:17
  • con quel codice mi dice che non trova : 

    'X509Certificate2UI' does not exist in the current context

    Non dovrebbe trovarmelo avendo messo

    using System.Security.Cryptography.X509Certificates;

    ?

    mercoledì 20 ottobre 2021 09:53
  • ITextSharp.dll versione 5.5.13.1

    • Modificato fabiocaruso mercoledì 20 ottobre 2021 14:31
    mercoledì 20 ottobre 2021 14:21
  • Per X509Certificate2UI, devi aggiungere il riferimento alla System.Security.dll, cercandola nella cartella che ho indicato sopra:

    in Visual Studio, vai nel riquadro a destra "Esplora soluzioni", clicca su "Riferimenti->Aggiungi riferimento" e selezioni il file System.Security.dll prendendolo in "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Security.dll" (o in un'altra cartella equivalente, se vuoi farlo funzionare con versioni di .NETFramework successive).

    Altrimenti quella direttiva using non ti funziona.


    • Modificato fabiocaruso mercoledì 20 ottobre 2021 14:32
    mercoledì 20 ottobre 2021 14:28
  • Tutto perfetto.

    Unico dubbio : 

    te crei un file "-signed.pdf" mentre a me viene chiesto un "-signed.pdf.p7m" 

    In teoria basta cambiare il punto dove viene indicato il file di destinazione visto che l'algoritmo di cifratura è lo stesso ( DigestAlgorithms.SHA256 ) . Giusto ? 

    Grazie

    giovedì 21 ottobre 2021 09:27
  • No. Il codice che ho postato io, mette la firma PADES (che è diversa dalla CADES .P7M). Con la firma PADES, si possono firmare solo i file .PDF, mantenendo la stessa estensione, e possono essere letti e visualizzati con qualunque reader (es. Acrobat, o altro...) che riconosce automaticamente la firma.

    Invece la firma CADES (quella con estensione .P7M) può essere applicata a qualunque tipo di file (pure ai .pdf) ed è quella di cui si è sempre parlato nei messaggi precedenti, in questa stessa discussione. Qualunque tipo di file viene interamente codificato ed ha bisogno di un lettore apposito per la decodifica. Per intenderci, è il formato comunemente utilizzato per firmare le fatture elettroniche.

    giovedì 21 ottobre 2021 17:33