smartcard and ocsp

View: New views
1 Messages — Rating Filter:   Alert me  

smartcard and ocsp

by dziedrius () :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,
i need to sign pdf with timestamp and ocsp, but as long as i add second digest in this line:

pdfPkcs7.GetEncodedPKCS7(sha.Hash, cal, tsc, ocsp);

, acrobat reader says "document altered". If the line is like this:

pdfPkcs7.GetEncodedPKCS7(null, cal, tsc, ocsp);

acrobat reader is happy, but naturaly ocsp isn't added.
may be someone notices something wrong in my code?

    public X509Certificate2 GetCertificate()
        {
            var st = new X509Store(parameters.CertificateStore, parameters.CertificateLocation);
            st.Open(OpenFlags.ReadOnly);
            var col = st.Certificates;
            X509Certificate2 card = null;
            var sel = X509Certificate2UI.SelectFromCollection(col, parameters.ChooseCertificateTitle, parameters.ChooseCertificateMessage, X509SelectionFlag.SingleSelection);
            if (sel.Count > 0)
            {
                var en = sel.GetEnumerator();
                en.MoveNext();
                card = en.Current;
            }
            st.Close();
            return card;
        }

        static public byte[] SignMessage(Byte[] msg, X509Certificate2 signerCert, bool detached)
        {
            var contentInfo = new ContentInfo(msg);
            var signedCms = new SignedCms(contentInfo, detached);
            var cmsSigner = new CmsSigner(signerCert)
            {
                IncludeOption = X509IncludeOption.EndCertOnly
            };

            signedCms.ComputeSignature(cmsSigner, false);

            return signedCms.Encode();
        }

        public void SignDetached(string inputFileName, string outputFileName)
        {
            var certificate = GetCertificate();
            var chain = GetChain(certificate);

            var pdfReader = new PdfReader(inputFileName);
            var pdfStamper = PdfStamper.CreateSignature(pdfReader, new FileStream(outputFileName, FileMode.Create), '\0');
            var signatureAppearance = pdfStamper.SignatureAppearance;

            var pageSize = pdfReader.GetPageSizeWithRotation(1);
            signatureAppearance.SetVisibleSignature(new Rectangle(pageSize.Width - 200, pageSize.Height - 20, pageSize.Width, pageSize.Height), 1, null);
            signatureAppearance.SignDate = DateTime.Now;
            signatureAppearance.SetCrypto(null, chain, null, null);
            signatureAppearance.Reason = parameters.SignReason;
            signatureAppearance.Location = parameters.SignLocation;
            signatureAppearance.Acro6Layers = true;
            signatureAppearance.Render = PdfSignatureAppearance.SignatureRender.NameAndDescription;
            var dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED)
                          {
                              Date = new PdfDate(signatureAppearance.SignDate),
                              Name = PdfPKCS7.GetSubjectFields(chain[0]).GetField("CN")
                          };
            if (signatureAppearance.Reason != null)
                dic.Reason = signatureAppearance.Reason;
            if (signatureAppearance.Location != null)
                dic.Location = signatureAppearance.Location;
            signatureAppearance.CryptoDictionary = dic;

            const int csize = 15000;
            var exc = new Hashtable();
            exc[PdfName.CONTENTS] = csize * 2 + 2;
            signatureAppearance.PreClose(exc);

            var sha = new SHA1CryptoServiceProvider();
            var s = signatureAppearance.RangeStream;

            var memoryStream = new MemoryStream();
            int read;
            var buffer = new byte[8192];

            while ((read = s.Read(buffer, 0, 8192)) > 0)
            {
                memoryStream.Write(buffer, 0, read);
            }

            sha.ComputeHash(memoryStream.ToArray());
            var pk2 = SignMessage(memoryStream.ToArray(), certificate, true);

            var pdfPkcs7forDigests = new PdfPKCS7(pk2);

            var digest = pdfPkcs7forDigests.Digest;
            var rsaData = pdfPkcs7forDigests.RsaData;

            var pdfPkcs7 = new PdfPKCS7(null, chain, null, "SHA1", true);

            pdfPkcs7.SetExternalDigest(digest, rsaData, "RSA");

            var tsc = new TSAClientBouncyCastle(parameters.TimeStampServerUrl, null, null);

            var cal = DateTime.Now;
            byte[] ocsp = null;
            if (chain.Length >= 2)
            {
                var url = PdfPKCS7.GetOCSPURL(chain[0]);
                if (!string.IsNullOrEmpty(url))
                    ocsp = new OcspClientBouncyCastle(chain[0], chain[1], url).GetEncoded();
            }
            var sh = pdfPkcs7.GetAuthenticatedAttributeBytes(sha.Hash, cal, null);
            pdfPkcs7.Update(sh, 0, sh.Length);

            var encodedSig = pdfPkcs7.GetEncodedPKCS7(sha.Hash, cal, tsc, ocsp);
            if (csize + 2 < encodedSig.Length)
                throw new Exception("Not enough space");

            var outc = new byte[csize];

            var dic2 = new PdfDictionary();

            Array.Copy(encodedSig, 0, outc, 0, encodedSig.Length);

            dic2.Put(PdfName.CONTENTS, new PdfString(outc).SetHexWriting(true));
            signatureAppearance.Close(dic2);
        }

        private static X509Certificate[] GetChain(X509Certificate2 certificate2)
        {
            var chain = new X509Chain();
            chain.Build(certificate2);

            var orgChain = new List<X509Certificate>();

            foreach (var cert in chain.ChainElements)
            {
                orgChain.Add(GetBouncyCastleCertificate(cert.Certificate));
            }
            return orgChain.ToArray();
        }

        private static X509Certificate GetBouncyCastleCertificate(X509Certificate2 certificate)
        {
            var certificateMemoryStream = new MemoryStream(certificate.RawData);
            return new X509Certificate(
                X509CertificateStructure.GetInstance(new Asn1InputStream(certificateMemoryStream).ReadObject()));
        }