예제 #1
0
        /* Updates the /ByteRange with the provided value */
        private void UpdateByteRange(PdfPKCS7 pkcs7, PdfSignature signature)
        {
            PdfArray b = signature.GetByteRange();
            RandomAccessFileOrArray rf = document.GetReader().GetSafeFile();
            Stream rg = null;

            try {
                rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(rf.CreateSourceView(), b.ToLongArray(
                                                                                         )));
                byte[] buf = new byte[8192];
                int    rd;
                while ((rd = rg.JRead(buf, 0, buf.Length)) > 0)
                {
                    pkcs7.Update(buf, 0, rd);
                }
            }
            catch (Exception e) {
                throw new PdfException(e);
            }
            finally {
                try {
                    if (rg != null)
                    {
                        rg.Dispose();
                    }
                }
                catch (System.IO.IOException e) {
                    // this really shouldn't ever happen - the source view we use is based on a Safe view, which is a no-op anyway
                    throw new PdfException(e);
                }
            }
        }
예제 #2
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);
        }
예제 #3
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);
        }