3

I can't enabled LTV in my signed pdf. I have already reviewed some solutions, but none of them can help me. To sign i'm using SignDeferred. Please helpme. If need more information, i can tell you. You can see the code and give me some solutions or change in the code.

Note: i saw in other solutions that use SignDetached. Some can explain the differences.

private void signDocument()
{

    try
    {
        Cancelar = 0;
        /** cargando certificado */
        ICollection<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>();
        chain.Add(Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(certificadoLocalSeleccionado.x509Certificate));

        int filasArchivos = dgvListaDocumentos.RowCount;
        for (int posicionFiles = 0; posicionFiles < filasArchivos; posicionFiles++)
        {
            if (filasArchivos > 80)
            {
                frmEsperando.actualizarEtiqueta("Firmando " + (posicionFiles + 1) + " de " + (filasArchivos));
                System.Threading.Thread.Sleep(500);
            }
            else
            {
                frmEsperando.actualizarEtiqueta("Firmando " + (posicionFiles + 1) + " de " + (filasArchivos));
                System.Threading.Thread.Sleep(1000);

            }

            String rutaArchivo = lstRutaArchivos[posicionFiles];
            String nombreDocumentos = lstNombres[posicionFiles];

            String nombreFirma = "Sig" + DateTime.Now.ToString("ddMMyyyyHHmmss");

            /** Configurando Pdf - inicio */
            PdfReader reader = new PdfReader(rutaArchivo);
            MemoryStream os = new MemoryStream();
            PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);

            PdfSignatureAppearance appearance = stamper.SignatureAppearance;


            appearance.Reason = "Firma Digital - " + (string)Settings.Default["empresa"];
            appearance.Location = "Lima";

            iTextSharp.text.Rectangle rectanguloFirma = new iTextSharp.text.Rectangle(0, 0, 0, 0);
            appearance.SetVisibleSignature(rectanguloFirma, 1, nombreFirma);


            /** Configurando Pdf - fin */

            /** Firmando externamente pdf - inicio */
            IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
            MakeSignature.SignExternalContainer(appearance, external, 8192);
            /** Firmando externamente pdf - fin */

            /** obteniendo bytes de la firma externa pdf - inicio */
            byte[] bytesPdfFirmadoTemporal = os.ToArray();
            /** obteniendo bytes de la firma externa pdf - fin */

            /** obteniendo hash de documento */
            PdfReader readerTmp = new PdfReader(new RandomAccessFileOrArray(bytesPdfFirmadoTemporal), null); ;
            AcroFields acroFields = readerTmp.AcroFields;
            PdfDictionary pdfDictionary = acroFields.GetSignatureDictionary(nombreFirma);

            if (pdfDictionary == null)
            {
                throw new iTextSharp.text.DocumentException("No existe ningun campo con el nombre: " + nombreFirma);
            }

            if (!acroFields.SignatureCoversWholeDocument(nombreFirma))
            {
                throw new iTextSharp.text.DocumentException("Not the last signature");
            }

            PdfArray pdfArray = pdfDictionary.GetAsArray(PdfName.BYTERANGE);
            long[] gaps = pdfArray.AsLongArray();
            if (pdfArray.Size != 4 || gaps[0] != 0)
            {
                throw new iTextSharp.text.DocumentException("Single exclusion space supported");
            }

            IRandomAccessSource readerSource = readerTmp.SafeFile.CreateSourceView();
            //RASInputStream rASInputStream = new iTextSharp.text.io.RASInputStream(readerSource);
            RASInputStream rASInputStream = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(readerSource, gaps));

            PdfPKCS7 pdfPkcs7 = new PdfPKCS7(null, chain, "SHA256", false);
            //OID DEL ALGORTIMO SHA256 -> "2.16.840.1.101.3.4.2.1"
            byte[] digest = DigestAlgorithms.Digest(rASInputStream, "2.16.840.1.101.3.4.2.1");
            byte[] hash = pdfPkcs7.getAuthenticatedAttributeBytes(digest, null, null, CryptoStandard.CMS);

            readerTmp.Close();
            os.Close();

            /** firmando hash */
            byte[] signature = null;
            RSACryptoServiceProvider rsaAesCSP = null;
            RSACryptoServiceProvider privateKey = null;
            privateKey = certificadoLocalSeleccionado.x509Certificate.PrivateKey as RSACryptoServiceProvider;
            if (privateKey != null)
            {
                if (!privateKey.CspKeyContainerInfo.HardwareDevice)
                {
                    CspParameters cspParameters = new CspParameters();
                    cspParameters.KeyContainerName = privateKey.CspKeyContainerInfo.KeyContainerName;
                    cspParameters.KeyNumber = privateKey.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2;

                    rsaAesCSP = new RSACryptoServiceProvider(cspParameters);
                    rsaAesCSP.PersistKeyInCsp = true;
                }
                else
                {
                    rsaAesCSP = privateKey;
                }

                signature = rsaAesCSP.SignData(hash, new SHA256Managed());

            }
            /** incrustar firma digital - inicio */
            PdfReader readerFinal = new PdfReader(bytesPdfFirmadoTemporal);
            IExternalSignatureContainer externalFinal = new SignFastCoreSignatureContainer(chain, digest, signature);

            FileStream osFinal = new FileStream(txtDestino.Text + "\\" + nombreDocumentos, FileMode.Create);
            MakeSignature.SignDeferred(readerFinal, nombreFirma, osFinal, externalFinal);
            /** incrustar firma digital - fin */
            documentosfirmados++;
            osFinal.Close();
            readerFinal.Close();

        }
        lstRutaArchivos.Clear();
        lstNombres.Clear();

    }
    catch (System.Exception excepcion)
    {
        Cancelar = 1;
        MessageBox.Show(excepcion.Message, "SignFastDesktop", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

    }
}

Here, the code about SignFastCoreSignatureContainer.

using AppSignFastDesktop.Properties;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppSignFastDesktop
{
    public class SignFastCoreSignatureContainer : IExternalSignatureContainer
    {
        ICollection<Org.BouncyCastle.X509.X509Certificate> chain;
        byte[] digest;
        byte[] sign;


        public SignFastCoreSignatureContainer(ICollection<Org.BouncyCastle.X509.X509Certificate> _chain, byte[] _digest, byte[] _sign)
        {
            chain = _chain;
            digest = _digest;
            sign = _sign;
        }

        public byte[] Sign(Stream data)
        {
            try
            {
                PdfPKCS7 pdfPkcs7 = new PdfPKCS7(null, chain, "SHA256", false);

                ITSAClient timeStamp = null;

                if((int)Settings.Default["PermisoSelloTiempo"] == 1)
                {
                    timeStamp = getTimeStampResponse();
                }

                pdfPkcs7.SetExternalDigest(sign, null, "RSA");

                return pdfPkcs7.GetEncodedPKCS7(digest, timeStamp, null, null, CryptoStandard.CMS);

            }
            catch (Exception excepcion)
            {
                throw excepcion;
            }
        }

        public void ModifySigningDictionary(PdfDictionary signDic)
        {
            throw new NotImplementedException();
        }

        public ITSAClient getTimeStampResponse()
        {
            ITSAClient signTSAClient = null;

            try
            {
                ITSAClient tscFinal = new TSAClientBouncyCastle((string)Settings.Default["Url"], (string)Settings.Default["Usuario"], (string)Settings.Default["Contrasenia"]);
                signTSAClient = tscFinal;
            }
            catch(Exception e)
            {
                throw e;
            }
            return signTSAClient;
        }

    }
}

llinan
  • 31
  • 3
  • use detechad instead defered, MakeSignature.SignDetached(appearance, pks, chain, crlList, ocsp, null, 0, CryptoStandard.CMS); ref: https://stackoverflow.com/questions/52331403/i-want-to-sign-a-pdf-document-with-itextsharp-and-return-ltv-pdf-enabled-file – jhuamanchumo Aug 28 '19 at 16:28
  • Why i should to use signDetached? – llinan Aug 28 '19 at 16:30
  • First of all, you can use the `AdobeLtvEnabling` class from my answer to the question @jhuamanchumo linked to no matter whether you signed detached or deferred; the input if that class is the signed pdf. So please try it and report whether it worked or not. That being said, there is no obvious need for deferred signing in your code, and in that case one should prefer detached signing. But we don't know your `SignFastCoreSignatureContainer`, probably there is something special about it requiring deferred signing. – mkl Aug 28 '19 at 17:08
  • Hi mkl, i edit the question and add the SignFastCoreSignatureContainer class. I use this class to validate if the document will have embedded timestamp. But, i'll try with AdobeLtvEnabling. – llinan Aug 28 '19 at 17:33
  • Ok, there still is nothing requiring a deferred signature, so you could switch to detached signing which would make the code more compact. Nonetheless, your code is fairly clear, so there is no real necessity to switch. – mkl Aug 29 '19 at 04:20

0 Answers0