/// <summary>
        /// Prepare the data needed for digital signature. Unfortunately
        /// CAPICOM's client-side implementation both hashes **AND** signs
        /// passed in data instead of signing data already hashed, so the 
        /// **entire** PDF content bytes are needed.
        /// </summary>
        /// <param name="pdfIn">PDF file contents</param>
        /// <returns>
        /// Base64 encoded PDF content bytes client will sign.
        /// </returns>
        public string PreSign(byte[] pdfIn)
        {
            byte[] pdfRawContent = null;
            bool isOdd = true;
            var timeStamp = DateTime.Now;
            var pdfSignature = new PdfSignature(
                PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED
            );
            pdfSignature.Date = new PdfDate(timeStamp);
            var exclusionSizes = new Dictionary<PdfName, int>();
            exclusionSizes.Add(PdfName.CONTENTS, EXCLUSION_BUFFER * 2 + 2);
            PdfReader reader = null;
            int? signedFields = null;
            try
            {
                var cert = new WebCertificateReader().GetSigningCertificate();
                do
                {
                    ++DataReadCount;
                    reader = new PdfReader(pdfIn);
                    _acroFieldsWorker = new AcroFieldsReader(reader.AcroFields);
                    signedFields = signedFields ?? _acroFieldsWorker.SignedFields();
                    _memoryStream = new MemoryStream();
                    var stamper = signedFields == 0
                        ? PdfStamper.CreateSignature(reader, _memoryStream, '\0')
                        : PdfStamper.CreateSignature(reader, _memoryStream, '\0', null, true)
                    ;
                    _signatureAppearance = stamper.SignatureAppearance;
                    InitSignatureField(stamper);
                    pdfSignature.Reason = Reason;
                    _signatureAppearance.Certificate = cert;
                    _signatureAppearance.SignDate = timeStamp;
                    _signatureAppearance.CryptoDictionary = pdfSignature;
                    _signatureAppearance.PreClose(exclusionSizes);
                    using (Stream sapStream = _signatureAppearance.GetRangeStream())
                    {
                        using (var ms = new MemoryStream())
                        {
                            sapStream.CopyTo(ms);
                            pdfRawContent = ms.ToArray();
                        }

                        // pdfRawContent = StreamHandler.ReadAllBytes(sapStream);
                        // fix CAPICOM's broken implemetation: signature
                        // invalid if sapStream.Length is **ODD**
                        if ((pdfRawContent.Length % 2) == 0)
                        {
                            isOdd = false;
                        }
                        else
                        {
                            Reason += "\0";
                        }
                        DataSize = sapStream.Length;
                    }
                    // sanity check
                    if (DataReadCount > 2) throw new InvalidOperationException("DataReadCount");
                } while (isOdd);
            }
            catch { throw; }
            finally
            {
                HttpContext.Current.Session[InstanceLookupKey] = this;
                if (reader != null) { reader.Dispose(); }
            }
            return Convert.ToBase64String(pdfRawContent);
        }
Пример #2
0
        /// <summary>
        /// Prepare the data needed for digital signature. Unfortunately
        /// CAPICOM's client-side implementation both hashes **AND** signs
        /// passed in data instead of signing data already hashed, so the
        /// **entire** PDF content bytes are needed.
        /// </summary>
        /// <param name="pdfIn">PDF file contents</param>
        /// <returns>
        /// Base64 encoded PDF content bytes client will sign.
        /// </returns>
        public string PreSign(byte[] pdfIn)
        {
            byte[] pdfRawContent = null;
            bool   isOdd         = true;
            var    timeStamp     = DateTime.Now;
            var    pdfSignature  = new PdfSignature(
                PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED
                );

            pdfSignature.Date = new PdfDate(timeStamp);
            var exclusionSizes = new Dictionary <PdfName, int>();

            exclusionSizes.Add(PdfName.CONTENTS, EXCLUSION_BUFFER * 2 + 2);
            PdfReader reader       = null;
            int?      signedFields = null;

            try
            {
                var cert = new WebCertificateReader().GetSigningCertificate();
                do
                {
                    ++DataReadCount;
                    reader            = new PdfReader(pdfIn);
                    _acroFieldsWorker = new AcroFieldsReader(reader.AcroFields);
                    signedFields      = signedFields ?? _acroFieldsWorker.SignedFields();
                    _memoryStream     = new MemoryStream();
                    var stamper = signedFields == 0
                        ? PdfStamper.CreateSignature(reader, _memoryStream, '\0')
                        : PdfStamper.CreateSignature(reader, _memoryStream, '\0', null, true)
                    ;
                    _signatureAppearance = stamper.SignatureAppearance;
                    InitSignatureField(stamper);
                    pdfSignature.Reason = Reason;
                    _signatureAppearance.Certificate      = cert;
                    _signatureAppearance.SignDate         = timeStamp;
                    _signatureAppearance.CryptoDictionary = pdfSignature;
                    _signatureAppearance.PreClose(exclusionSizes);
                    using (Stream sapStream = _signatureAppearance.GetRangeStream())
                    {
                        using (var ms = new MemoryStream())
                        {
                            sapStream.CopyTo(ms);
                            pdfRawContent = ms.ToArray();
                        }

                        // pdfRawContent = StreamHandler.ReadAllBytes(sapStream);
                        // fix CAPICOM's broken implemetation: signature
                        // invalid if sapStream.Length is **ODD**
                        if ((pdfRawContent.Length % 2) == 0)
                        {
                            isOdd = false;
                        }
                        else
                        {
                            // Reason += '\0';
                            Reason += " ";
                        }
                        DataSize = sapStream.Length;
                    }
                    // sanity check
                    if (DataReadCount > 200)
                    {
                        throw new InvalidOperationException("DataReadCount");
                    }
                } while (isOdd);
            }
            catch { throw; }
            finally
            {
                HttpContext.Current.Session[InstanceLookupKey] = this;
                if (reader != null)
                {
                    reader.Dispose();
                }
            }
            return(Convert.ToBase64String(pdfRawContent));
        }