예제 #1
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.ThisInstanceOfPdfSignerIsAlreadyClosed);
            }
            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;
        }