예제 #1
0
        /**
         * Sign the document using an external container, usually a PKCS7. The signature is fully composed
         * externally, iText will just put the container inside the document.
         * @param sap the PdfSignatureAppearance
         * @param externalSignatureContainer the interface providing the actual signing
         * @param estimatedSize the reserved size for the signature
         * @throws GeneralSecurityException
         * @throws IOException
         * @throws DocumentException
         */
        public static void SignExternalContainer(PdfSignatureAppearance sap, IExternalSignatureContainer externalSignatureContainer, int estimatedSize)
        {
            PdfSignature dic = new PdfSignature(null, null);

            dic.Reason           = sap.Reason;
            dic.Location         = sap.Location;
            dic.SignatureCreator = sap.SignatureCreator;
            dic.Contact          = sap.Contact;
            dic.Date             = new PdfDate(sap.SignDate); // time-stamp will over-rule this
            externalSignatureContainer.ModifySigningDictionary(dic);
            sap.CryptoDictionary = dic;

            Dictionary <PdfName, int> exc = new Dictionary <PdfName, int>();

            exc[PdfName.CONTENTS] = estimatedSize * 2 + 2;
            sap.PreClose(exc);

            Stream data = sap.GetRangeStream();

            byte[] encodedSig = externalSignatureContainer.Sign(data);

            if (estimatedSize < encodedSig.Length)
            {
                throw new IOException("Not enough space");
            }

            byte[] paddedSig = new byte[estimatedSize];
            System.Array.Copy(encodedSig, 0, paddedSig, 0, encodedSig.Length);

            PdfDictionary dic2 = new PdfDictionary();

            dic2.Put(PdfName.CONTENTS, new PdfString(paddedSig).SetHexWriting(true));
            sap.Close(dic2);
        }
예제 #2
0
        /// <summary>Sign the document using an external container, usually a PKCS7.</summary>
        /// <remarks>
        /// Sign the document using an external container, usually a PKCS7. The signature is fully composed
        /// externally, iText will just put the container inside the document.
        /// <br /><br />
        /// NOTE: This method closes the underlying pdf document. This means, that current instance
        /// of PdfSigner cannot be used after this method call.
        /// </remarks>
        /// <param name="externalSignatureContainer">the interface providing the actual signing</param>
        /// <param name="estimatedSize">the reserved size for the signature</param>
        /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/>
        /// <exception cref="System.IO.IOException"/>
        public virtual void SignExternalContainer(IExternalSignatureContainer externalSignatureContainer, int estimatedSize
                                                  )
        {
            if (closed)
            {
                throw new PdfException(PdfException.ThisInstanceOfPdfSignerAlreadyClosed);
            }
            PdfSignature           dic        = new PdfSignature();
            PdfSignatureAppearance appearance = GetSignatureAppearance();

            dic.SetReason(appearance.GetReason());
            dic.SetLocation(appearance.GetLocation());
            dic.SetSignatureCreator(appearance.GetSignatureCreator());
            dic.SetContact(appearance.GetContact());
            dic.SetDate(new PdfDate(GetSignDate()));
            // time-stamp will over-rule this
            externalSignatureContainer.ModifySigningDictionary(dic.GetPdfObject());
            cryptoDictionary = dic;
            IDictionary <PdfName, int?> exc = new Dictionary <PdfName, int?>();

            exc[PdfName.Contents] = estimatedSize * 2 + 2;
            PreClose(exc);
            Stream data = GetRangeStream();

            byte[] encodedSig = externalSignatureContainer.Sign(data);
            if (estimatedSize < encodedSig.Length)
            {
                throw new System.IO.IOException("Not enough space");
            }
            byte[] paddedSig = new byte[estimatedSize];
            System.Array.Copy(encodedSig, 0, paddedSig, 0, encodedSig.Length);
            PdfDictionary dic2 = new PdfDictionary();

            dic2.Put(PdfName.Contents, new PdfString(paddedSig).SetHexWriting(true));
            Close(dic2);
            closed = true;
        }
 /**
  * Signs a PDF where space was already reserved.
  * @param reader the original PDF
  * @param fieldName the field to sign. It must be the last field
  * @param outs the output PDF
  * @param externalSignatureContainer the signature container doing the actual signing. Only the 
  * method ExternalSignatureContainer.sign is used
  * @throws DocumentException
  * @throws IOException
  * @throws GeneralSecurityException 
  */
 public static void SignDeferred(PdfReader reader, String fieldName, Stream outs, IExternalSignatureContainer externalSignatureContainer) {
     AcroFields af = reader.AcroFields;
     PdfDictionary v = af.GetSignatureDictionary(fieldName);
     if (v == null)
         throw new DocumentException("No field");
     if (!af.SignatureCoversWholeDocument(fieldName))
         throw new DocumentException("Not the last signature");
     PdfArray b = v.GetAsArray(PdfName.BYTERANGE);
     long[] gaps = b.AsLongArray();
     if (b.Size != 4 || gaps[0] != 0)
         throw new DocumentException("Single exclusion space supported");
     IRandomAccessSource readerSource = reader.SafeFile.CreateSourceView();
     Stream rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(readerSource, gaps));
     byte[] signedContent = externalSignatureContainer.Sign(rg);
     int spaceAvailable = (int)(gaps[2] - gaps[1]) - 2;
     if ((spaceAvailable & 1) != 0)
         throw new DocumentException("Gap is not a multiple of 2");
     spaceAvailable /= 2;
     if (spaceAvailable < signedContent.Length)
         throw new DocumentException("Not enough space");
     StreamUtil.CopyBytes(readerSource, 0, gaps[1] + 1, outs);
     ByteBuffer bb = new ByteBuffer(spaceAvailable * 2);
     foreach (byte bi in signedContent) {
         bb.AppendHex(bi);
     }
     int remain = (spaceAvailable - signedContent.Length) * 2;
     for (int k = 0; k < remain; ++k) {
         bb.Append((byte)48);
     }
     bb.WriteTo(outs);
     StreamUtil.CopyBytes(readerSource, gaps[2] - 1, gaps[3] + 1, outs);
 }
        /**
         * Sign the document using an external container, usually a PKCS7. The signature is fully composed
         * externally, iText will just put the container inside the document.
         * @param sap the PdfSignatureAppearance
         * @param externalSignatureContainer the interface providing the actual signing
         * @param estimatedSize the reserved size for the signature
         * @throws GeneralSecurityException
         * @throws IOException
         * @throws DocumentException 
         */
        public static void SignExternalContainer(PdfSignatureAppearance sap, IExternalSignatureContainer externalSignatureContainer, int estimatedSize) {
            PdfSignature dic = new PdfSignature(null, null);
            dic.Reason = sap.Reason;
            dic.Location = sap.Location;
            dic.SignatureCreator = sap.SignatureCreator;
            dic.Contact = sap.Contact;
            dic.Date = new PdfDate(sap.SignDate); // time-stamp will over-rule this
            externalSignatureContainer.ModifySigningDictionary(dic);
            sap.CryptoDictionary = dic;

            Dictionary<PdfName, int> exc = new Dictionary<PdfName, int>();
            exc[PdfName.CONTENTS] = estimatedSize * 2 + 2;
            sap.PreClose(exc);

            Stream data = sap.GetRangeStream();
            byte[] encodedSig = externalSignatureContainer.Sign(data);

            if (estimatedSize < encodedSig.Length)
                throw new IOException("Not enough space");

            byte[] paddedSig = new byte[estimatedSize];
            System.Array.Copy(encodedSig, 0, paddedSig, 0, encodedSig.Length);

            PdfDictionary dic2 = new PdfDictionary();
            dic2.Put(PdfName.CONTENTS, new PdfString(paddedSig).SetHexWriting(true));
            sap.Close(dic2);
        }
예제 #5
0
        /**
         * Signs a PDF where space was already reserved.
         * @param reader the original PDF
         * @param fieldName the field to sign. It must be the last field
         * @param outs the output PDF
         * @param externalSignatureContainer the signature container doing the actual signing. Only the
         * method ExternalSignatureContainer.sign is used
         * @throws DocumentException
         * @throws IOException
         * @throws GeneralSecurityException
         */
        public static void SignDeferred(PdfReader reader, String fieldName, Stream outs, IExternalSignatureContainer externalSignatureContainer)
        {
            AcroFields    af = reader.AcroFields;
            PdfDictionary v  = af.GetSignatureDictionary(fieldName);

            if (v == null)
            {
                throw new DocumentException("No field");
            }
            if (!af.SignatureCoversWholeDocument(fieldName))
            {
                throw new DocumentException("Not the last signature");
            }
            PdfArray b = v.GetAsArray(PdfName.BYTERANGE);

            long[] gaps = b.AsLongArray();
            if (b.Size != 4 || gaps[0] != 0)
            {
                throw new DocumentException("Single exclusion space supported");
            }
            IRandomAccessSource readerSource = reader.SafeFile.CreateSourceView();
            Stream rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(readerSource, gaps));

            byte[] signedContent  = externalSignatureContainer.Sign(rg);
            int    spaceAvailable = (int)(gaps[2] - gaps[1]) - 2;

            if ((spaceAvailable & 1) != 0)
            {
                throw new DocumentException("Gap is not a multiple of 2");
            }
            spaceAvailable /= 2;
            if (spaceAvailable < signedContent.Length)
            {
                throw new DocumentException("Not enough space");
            }
            StreamUtil.CopyBytes(readerSource, 0, gaps[1] + 1, outs);
            ByteBuffer bb = new ByteBuffer(spaceAvailable * 2);

            foreach (byte bi in signedContent)
            {
                bb.AppendHex(bi);
            }
            int remain = (spaceAvailable - signedContent.Length) * 2;

            for (int k = 0; k < remain; ++k)
            {
                bb.Append((byte)48);
            }
            bb.WriteTo(outs);
            StreamUtil.CopyBytes(readerSource, gaps[2] - 1, gaps[3] + 1, outs);
        }
예제 #6
0
        /// <summary>Signs a PDF where space was already reserved.</summary>
        /// <param name="document">the original PDF</param>
        /// <param name="fieldName">the field to sign. It must be the last field</param>
        /// <param name="outs">the output PDF</param>
        /// <param name="externalSignatureContainer">
        /// the signature container doing the actual signing. Only the
        /// method ExternalSignatureContainer.sign is used
        /// </param>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/>
        public static void SignDeferred(PdfDocument document, String fieldName, Stream outs, IExternalSignatureContainer
                                        externalSignatureContainer)
        {
            SignatureUtil signatureUtil = new SignatureUtil(document);
            PdfDictionary v             = signatureUtil.GetSignatureDictionary(fieldName);

            if (v == null)
            {
                throw new PdfException(PdfException.ThereIsNoFieldInTheDocumentWithSuchName1).SetMessageParams(fieldName);
            }
            if (!signatureUtil.SignatureCoversWholeDocument(fieldName))
            {
                new PdfException(PdfException.SignatureWithName1IsNotTheLastItDoesntCoverWholeDocument).SetMessageParams(fieldName
                                                                                                                         );
            }
            PdfArray b = v.GetAsArray(PdfName.ByteRange);

            long[] gaps = SignatureUtil.AsLongArray(b);
            // TODO: refactor
            if (b.Size() != 4 || gaps[0] != 0)
            {
                throw new ArgumentException("Single exclusion space supported");
            }
            IRandomAccessSource readerSource = document.GetReader().GetSafeFile().CreateSourceView();
            Stream rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(readerSource, gaps));

            byte[] signedContent  = externalSignatureContainer.Sign(rg);
            int    spaceAvailable = (int)(gaps[2] - gaps[1]) - 2;

            if ((spaceAvailable & 1) != 0)
            {
                throw new ArgumentException("Gap is not a multiple of 2");
            }
            spaceAvailable /= 2;
            if (spaceAvailable < signedContent.Length)
            {
                throw new PdfException(PdfException.AvailableSpaceIsNotEnoughForSignature);
            }
            StreamUtil.CopyBytes(readerSource, 0, gaps[1] + 1, outs);
            ByteBuffer bb = new ByteBuffer(spaceAvailable * 2);

            foreach (byte bi in signedContent)
            {
                bb.AppendHex(bi);
            }
            int remain = (spaceAvailable - signedContent.Length) * 2;

            for (int k = 0; k < remain; ++k)
            {
                bb.Append((byte)48);
            }
            byte[] bbArr = bb.ToByteArray();
            outs.Write(bbArr);
            StreamUtil.CopyBytes(readerSource, gaps[2] - 1, gaps[3] + 1, outs);
        }