Beispiel #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);
                }
            }
        }
Beispiel #2
0
        /// <summary>Adds keys to the signature dictionary that define the field permissions.</summary>
        /// <remarks>
        /// Adds keys to the signature dictionary that define the field permissions.
        /// This method is only used for signatures that lock fields.
        /// </remarks>
        /// <param name="crypto">the signature dictionary</param>
        protected internal virtual void AddFieldMDP(PdfSignature crypto, PdfSigFieldLockDictionary fieldLock)
        {
            PdfDictionary reference       = new PdfDictionary();
            PdfDictionary transformParams = new PdfDictionary();

            transformParams.PutAll(fieldLock.GetPdfObject());
            transformParams.Put(PdfName.Type, PdfName.TransformParams);
            transformParams.Put(PdfName.V, new PdfName("1.2"));
            reference.Put(PdfName.TransformMethod, PdfName.FieldMDP);
            reference.Put(PdfName.Type, PdfName.SigRef);
            reference.Put(PdfName.TransformParams, transformParams);
            reference.Put(new PdfName("DigestValue"), new PdfString("aa"));
            PdfArray loc = new PdfArray();

            loc.Add(new PdfNumber(0));
            loc.Add(new PdfNumber(0));
            reference.Put(new PdfName("DigestLocation"), loc);
            reference.Put(new PdfName("DigestMethod"), new PdfName("MD5"));
            reference.Put(PdfName.Data, document.GetTrailer().Get(PdfName.Root));
            PdfArray types = crypto.GetPdfObject().GetAsArray(PdfName.Reference);

            if (types == null)
            {
                types = new PdfArray();
            }
            types.Add(reference);
            crypto.Put(PdfName.Reference, types);
        }
Beispiel #3
0
        /// <summary>Adds keys to the signature dictionary that define the certification level and the permissions.</summary>
        /// <remarks>
        /// Adds keys to the signature dictionary that define the certification level and the permissions.
        /// This method is only used for Certifying signatures.
        /// </remarks>
        /// <param name="crypto">the signature dictionary</param>
        protected internal virtual void AddDocMDP(PdfSignature crypto)
        {
            PdfDictionary reference       = new PdfDictionary();
            PdfDictionary transformParams = new PdfDictionary();

            transformParams.Put(PdfName.P, new PdfNumber(certificationLevel));
            transformParams.Put(PdfName.V, new PdfName("1.2"));
            transformParams.Put(PdfName.Type, PdfName.TransformParams);
            reference.Put(PdfName.TransformMethod, PdfName.DocMDP);
            reference.Put(PdfName.Type, PdfName.SigRef);
            reference.Put(PdfName.TransformParams, transformParams);
            if (document.GetPdfVersion().CompareTo(PdfVersion.PDF_1_6) < 0)
            {
                reference.Put(new PdfName("DigestValue"), new PdfString("aa"));
                PdfArray loc = new PdfArray();
                loc.Add(new PdfNumber(0));
                loc.Add(new PdfNumber(0));
                reference.Put(new PdfName("DigestLocation"), loc);
                reference.Put(new PdfName("DigestMethod"), new PdfName("MD5"));
            }
            reference.Put(PdfName.Data, document.GetTrailer().Get(PdfName.Root));
            PdfArray types = new PdfArray();

            types.Add(reference);
            crypto.Put(PdfName.Reference, types);
        }
Beispiel #4
0
        /// <summary>
        /// Prepares an
        /// <see cref="PdfPKCS7"/>
        /// instance for the given signature.
        /// This method handles signature parsing and might throw an exception if
        /// signature is malformed.
        /// <p>
        /// The returned
        /// <see cref="PdfPKCS7"/>
        /// can be used to fetch additional info about the signature
        /// and also to perform integrity check of data signed by the given signature field.
        /// </p>
        /// Prepared
        /// <see cref="PdfPKCS7"/>
        /// instance calculates digest based on signature's /ByteRange entry.
        /// In order to check that /ByteRange is properly defined and given signature indeed covers the current PDF document
        /// revision please use
        /// <see cref="SignatureCoversWholeDocument(System.String)"/>
        /// method.
        /// </summary>
        /// <param name="signatureFieldName">the signature field name</param>
        /// <param name="securityProvider">the security provider or null for the default provider</param>
        /// <returns>
        /// a
        /// <see cref="PdfPKCS7"/>
        /// instance which can be used to fetch additional info about the signature
        /// and also to perform integrity check of data signed by the given signature field.
        /// </returns>
        public virtual PdfPKCS7 ReadSignatureData(String signatureFieldName)
        {
            PdfSignature signature = GetSignature(signatureFieldName);

            if (signature == null)
            {
                return(null);
            }
            try {
                PdfName   sub      = signature.GetSubFilter();
                PdfString contents = signature.GetContents();
                PdfPKCS7  pk       = null;
                if (sub.Equals(PdfName.Adbe_x509_rsa_sha1))
                {
                    PdfString cert = signature.GetPdfObject().GetAsString(PdfName.Cert);
                    if (cert == null)
                    {
                        cert = signature.GetPdfObject().GetAsArray(PdfName.Cert).GetAsString(0);
                    }
                    pk = new PdfPKCS7(PdfEncodings.ConvertToBytes(contents.GetValue(), null), cert.GetValueBytes());
                }
                else
                {
                    pk = new PdfPKCS7(PdfEncodings.ConvertToBytes(contents.GetValue(), null), sub);
                }
                UpdateByteRange(pk, signature);
                PdfString date = signature.GetDate();
                if (date != null)
                {
                    pk.SetSignDate(PdfDate.Decode(date.ToString()));
                }
                String signName = signature.GetName();
                pk.SetSignName(signName);
                String reason = signature.GetReason();
                if (reason != null)
                {
                    pk.SetReason(reason);
                }
                String location = signature.GetLocation();
                if (location != null)
                {
                    pk.SetLocation(location);
                }
                return(pk);
            }
            catch (Exception e) {
                throw new PdfException(e);
            }
        }
Beispiel #5
0
        /// <summary>Signs a document with a PAdES-LTV Timestamp.</summary>
        /// <remarks>
        /// Signs a document with a PAdES-LTV Timestamp. The document is closed at the end.
        /// <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="tsa">the timestamp generator</param>
        /// <param name="signatureName">
        /// the signature name or null to have a name generated
        /// automatically
        /// </param>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/>
        public virtual void Timestamp(ITSAClient tsa, String signatureName)
        {
            if (closed)
            {
                throw new PdfException(PdfException.ThisInstanceOfPdfSignerAlreadyClosed);
            }
            int contentEstimated = tsa.GetTokenSizeEstimate();

            AddDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL5);
            SetFieldName(signatureName);
            PdfSignature dic = new PdfSignature(PdfName.Adobe_PPKLite, PdfName.ETSI_RFC3161);

            dic.Put(PdfName.Type, PdfName.DocTimeStamp);
            cryptoDictionary = dic;
            IDictionary <PdfName, int?> exc = new Dictionary <PdfName, int?>();

            exc[PdfName.Contents] = contentEstimated * 2 + 2;
            PreClose(exc);
            Stream  data          = GetRangeStream();
            IDigest messageDigest = tsa.GetMessageDigest();

            byte[] buf = new byte[4096];
            int    n;

            while ((n = data.Read(buf)) > 0)
            {
                messageDigest.Update(buf, 0, n);
            }
            byte[] tsImprint = messageDigest.Digest();
            byte[] tsToken;
            try {
                tsToken = tsa.GetTimeStampToken(tsImprint);
            }
            catch (Exception e) {
                throw new GeneralSecurityException(e.Message, e);
            }
            if (contentEstimated + 2 < tsToken.Length)
            {
                throw new System.IO.IOException("Not enough space");
            }
            byte[] paddedSig = new byte[contentEstimated];
            System.Array.Copy(tsToken, 0, paddedSig, 0, tsToken.Length);
            PdfDictionary dic2 = new PdfDictionary();

            dic2.Put(PdfName.Contents, new PdfString(paddedSig).SetHexWriting(true));
            Close(dic2);
            closed = true;
        }
        /// <exception cref="Org.BouncyCastle.Security.SecurityUtilityException"/>
        /// <exception cref="System.IO.IOException"/>
        private PdfName GetSignatureHashKey(String signatureName)
        {
            PdfSignature sig      = sgnUtil.GetSignature(signatureName);
            PdfString    contents = sig.GetContents();

            byte[] bc = PdfEncodings.ConvertToBytes(contents.GetValue(), null);
            byte[] bt = null;
            if (PdfName.ETSI_RFC3161.Equals(sig.GetSubFilter()))
            {
                Asn1InputStream din  = new Asn1InputStream(new MemoryStream(bc));
                Asn1Object      pkcs = din.ReadObject();
                bc = pkcs.GetEncoded();
            }
            bt = HashBytesSha1(bc);
            return(new PdfName(ConvertToHex(bt)));
        }
Beispiel #7
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;
        }
Beispiel #8
0
        /// <summary>Signs the document using the detached mode, CMS or CAdES equivalent.</summary>
        /// <remarks>
        /// Signs the document using the detached mode, CMS or CAdES equivalent.
        /// <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="externalSignature">the interface providing the actual signing</param>
        /// <param name="chain">the certificate chain</param>
        /// <param name="crlList">the CRL list</param>
        /// <param name="ocspClient">the OCSP client</param>
        /// <param name="tsaClient">the Timestamp client</param>
        /// <param name="externalDigest">an implementation that provides the digest</param>
        /// <param name="estimatedSize">the reserved size for the signature. It will be estimated if 0</param>
        /// <param name="sigtype">Either Signature.CMS or Signature.CADES</param>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/>
        public virtual void SignDetached(IExternalSignature externalSignature, X509Certificate[] chain, ICollection
                                         <ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize, PdfSigner.CryptoStandard
                                         sigtype)
        {
            if (closed)
            {
                throw new PdfException(PdfException.ThisInstanceOfPdfSignerAlreadyClosed);
            }
            ICollection <byte[]> crlBytes = null;
            int i = 0;

            while (crlBytes == null && i < chain.Length)
            {
                crlBytes = ProcessCrl(chain[i++], crlList);
            }
            if (estimatedSize == 0)
            {
                estimatedSize = 8192;
                if (crlBytes != null)
                {
                    foreach (byte[] element in crlBytes)
                    {
                        estimatedSize += element.Length + 10;
                    }
                }
                if (ocspClient != null)
                {
                    estimatedSize += 4192;
                }
                if (tsaClient != null)
                {
                    estimatedSize += 4192;
                }
            }
            PdfSignatureAppearance appearance = GetSignatureAppearance();

            appearance.SetCertificate(chain[0]);
            if (sigtype == PdfSigner.CryptoStandard.CADES)
            {
                AddDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL2);
            }
            PdfSignature dic = new PdfSignature(PdfName.Adobe_PPKLite, sigtype == PdfSigner.CryptoStandard.CADES ? PdfName
                                                .ETSI_CAdES_DETACHED : PdfName.Adbe_pkcs7_detached);

            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
            cryptoDictionary = dic;
            IDictionary <PdfName, int?> exc = new Dictionary <PdfName, int?>();

            exc[PdfName.Contents] = estimatedSize * 2 + 2;
            PreClose(exc);
            String   hashAlgorithm = externalSignature.GetHashAlgorithm();
            PdfPKCS7 sgn           = new PdfPKCS7((ICipherParameters)null, chain, hashAlgorithm, false);
            Stream   data          = GetRangeStream();

            byte[] hash = DigestAlgorithms.Digest(data, SignUtils.GetMessageDigest(hashAlgorithm));
            byte[] ocsp = null;
            if (chain.Length >= 2 && ocspClient != null)
            {
                ocsp = ocspClient.GetEncoded((X509Certificate)chain[0], (X509Certificate)chain[1], null);
            }
            byte[] sh           = sgn.GetAuthenticatedAttributeBytes(hash, ocsp, crlBytes, sigtype);
            byte[] extSignature = externalSignature.Sign(sh);
            sgn.SetExternalDigest(extSignature, null, externalSignature.GetEncryptionAlgorithm());
            byte[] encodedSig = sgn.GetEncodedPKCS7(hash, tsaClient, ocsp, crlBytes, sigtype);
            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;
        }