I have specifically checked the chain. It shows there are 3 completely separate 
certificates in it.
With the information you have given me though, I was able to track down where 
the problem is.

The chain in the setCrypto method isn't getting used in the Certificate 
Dictionary because I'm setting the dictionary manually and we aren't passing in 
any kind of ICipherParameters into the SetCrypto method. (It's this way in your 
online examples)
To get it to work correctly I changed the cmsSigner.IncludeOption to 
ExcludeRoot instead of EndCertificateOnly and the problem was solved, all of 
the intermediate certs were sent. If you want the root to be sent as well, you 
can use WholeChain.
I also had to change csize variable. I did a more dynamic approach then just 
saying 4000. I did 4000 plus the sum of the length of the raw data of all the 
certs in the chain.

As I find it annoying when people find an answer, but don't share, here's my 
entire code.

using System;
using System.Configuration;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.Linq;

namespace PDFStuff
{
    class PDFPlayground
    {

        public static X509Store GetStore()
        {
            X509Store store = new X509Store(StoreName.My, 
StoreLocation.LocalMachine);
            store.Open(OpenFlags.MaxAllowed);
            return store;
        }

        public static X509Certificate2 GetCertificateByThumbprint(string 
thumbprint, bool requirePrivate)
        {
            if (string.IsNullOrEmpty(thumbprint))
            {
                return null;
            }

            X509Store store = GetStore();
            X509Certificate2 result = null;
            try
            {
                foreach (X509Certificate2 c in store.Certificates)
                {
                    if (c.Thumbprint == thumbprint &&
                        (c.HasPrivateKey || !requirePrivate))
                        result = c;
                }
            }
            catch
            {
            }
            finally
            {
                store.Close();
            }

            return result;
        }

        public static byte[] SignDocument(byte[] pdfDocument)
        {
            //get the certificate
            X509Certificate2 cert = 
GetCertificateByThumbprint(ConfigurationManager.AppSettings["PDFCertificateThumbprint"],
 true);

            if (cert == null)
            {
                //no cert, dont do anything
                return pdfDocument;
            }


            using (MemoryStream stream = new MemoryStream())
            {
                //set initial variables
                X509Chain chain = X509Chain.Create();
                PdfReader reader = new PdfReader(pdfDocument);
                PdfStamper stamper = PdfStamper.CreateSignature(reader, stream, 
'\0', null, false);
                PdfSignatureAppearance sap = stamper.SignatureAppearance;
                PdfSignature signatureDictionary = new 
PdfSignature(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
                Dictionary<PdfName, int> reservedSpace = new 
Dictionary<PdfName, int>();
                HashAlgorithm sha = new SHA1CryptoServiceProvider();
                int read = 0;
                byte[] buff = new byte[8192];
                int csize = 0;
                byte[] outc = null;
                Stream sapStream = null;
                byte[] pk = null;
                PdfDictionary certificateDictionary = new PdfDictionary();

                //build my certificate chain
                chain.Build(cert);

                //guess the size of the certificates and signature.
                //we don't know for sure how big it really is going to be until 
after we hash it, so, we give it 4k for the signature
                //and add the size of all the raw data of the certificates.
                csize = 4096 +  //4K for the signature
                    (from c in chain.ChainElements.OfType<X509ChainElement>()
                     select c.Certificate.RawData.Length).Sum(); //add up the 
size of each of the certificates and add it up

                //certificate buffer
                outc = new byte[csize];

                //protect certain features of the document
                stamper.SetEncryption(null,
                    Guid.NewGuid().ToByteArray(), //random password
                    PdfWriter.ALLOW_PRINTING |
                    PdfWriter.ALLOW_COPY |
                    PdfWriter.ALLOW_SCREENREADERS,
                    PdfWriter.ENCRYPTION_AES_256);


                //////sign the document
                sap.SetVisibleSignature(new Rectangle(1, 1, 1, 1), 1, 
"Signature field"); //we use a rectangle of 1,1,1,1 to hide it.
                sap.SignDate = DateTime.Parse(cert.GetEffectiveDateString());
                sap.Reason = "reason, i am"; //reason for being signed
                sap.Location = "location, i am not"; //location it was signed

                //set to use the wincer_signed, its a windows cert, not sure if 
this is needed.
                sap.SetCrypto(null, null, null, 
PdfSignatureAppearance.WINCER_SIGNED);

                //set some stuff in the signature dictionary. we dont need to 
set the appearance stuff because the signature is hidden.
                signatureDictionary.Reason = sap.Reason;
                signatureDictionary.Location = sap.Location;
                signatureDictionary.Date = new PdfDate(sap.SignDate);
                signatureDictionary.Name = cert.Subject; //certificate name

                //set the appearance only stuff.
                sap.Acro6Layers = true; //set to true to make adobe 6.x and 
higher happier with the layers.
                sap.Render = 
PdfSignatureAppearance.SignatureRender.NameAndDescription; //what to show in 
the signature display. since its hidden, we dont care
                //                                                              
          but if we do allow an image, then we have to put in an image.

                //set the crypto dictionary
                sap.CryptoDictionary = signatureDictionary;

                //reserve some space for certs and signatures
                reservedSpace[PdfName.CONTENTS] = csize * 2 + 2; //*2 because 
binary data is stored as hex strings (i think). +2 for end of field
                sap.PreClose(reservedSpace); //actually reserve it

                //build the signature
                sapStream = sap.RangeStream;
                while ((read = sapStream.Read(buff, 0, 8192)) > 0)
                {
                    sha.TransformBlock(buff, 0, read, buff, 0);
                }
                sha.TransformFinalBlock(buff, 0, 0);
                pk = SignMsg(sha.Hash, chain, false);

                //put the certs and signature into the reserved buffer
                Array.Copy(pk, 0, outc, 0, pk.Length);

                //put the reserved buffer into the reserved space
                certificateDictionary.Put(PdfName.CONTENTS, new 
PdfString(outc).SetHexWriting(true));

                //write the signature
                sap.Close(certificateDictionary);

                //close the stamper and save it
                stamper.Close();

                //close the reader
                reader.Close();

                //return the saved pdf
                return stream.GetBuffer();
            }
        }

        public static byte[] SignMsg(Byte[] msg, X509Chain chain, bool detached)
        {
            //  Place message in a ContentInfo object.
            //  This is required to build a SignedCms object.
            ContentInfo contentInfo = new ContentInfo(msg);

            //  Instantiate SignedCms object with the ContentInfo above.
            //  Has default SubjectIdentifierType IssuerAndSerialNumber.
            SignedCms signedCms = new SignedCms(contentInfo, detached);

            //  Formulate a CmsSigner object for the signer.
            CmsSigner cmsSigner = new 
CmsSigner(chain.ChainElements[0].Certificate); //first cert in the chain is the 
signer cert

            //  Do the whole certificate chain. This way intermediate 
certificates get sent across as well.
            cmsSigner.IncludeOption = X509IncludeOption.ExcludeRoot;

            //  Sign the CMS/PKCS #7 message. The second argument is
            //  needed to ask for the pin.
            signedCms.ComputeSignature(cmsSigner, false);

            //  Encode the CMS/PKCS #7 message.
            return signedCms.Encode();
        }
    }
}

Edward Cooke
Programmer II, Information Systems
+1 801-325-6143 tel
+1 801-898-5940 cell
eco...@macu.com
http://www.macu.com

https://images.mtnam.org/marketing/image.aspx/1
https://images.mtnam.org/marketing/image.aspx/3/fb 
https://images.mtnam.org/marketing/image.aspx/3/tw



--------------------------------------------------------------------------

From: mkl [mailto:m...@wir-sind-cool.org]
Sent: Wednesday, August 24, 2011 5:55 AM
To: itext-questions@lists.sourceforge.net
Subject: Re: [iText-questions] iTextSharp and certificate chains using windows 
certificate store

Edward,

Edward Cooke wrote:
> Here's my signed document.

Your impression is right that there only is one certificate, the user 
certificate, included in the signature.

On the other hand I also looked at the code (more exactly: the Java code, but 
as nothing magical happens there, I assume that the C# code is equivalent); it 
simply takes the certificates given to it in PdfSignatureAppearance.setCrypto 
and stores them locally; it forwards them to other objects; later it uses these 
certificates and adds them to the
PKCS#7 signature container. So every certificate you use in setCrypto should be 
included in the signature container.

BTW, it also implicitly expects the first certificate to be the user 
certificate. You initially wrote:


> I've tried adding the entire chain into the array of certificates, in
> both root cert first, signing one last and signing one first the root
> last. But adobe is showing that only the signing cert is being put in.

Thus, if changing the order of the certificates in the list has no effect, most 
likely the list does not contain more than one element.

So, have you actually checked the size of the OrgX509.X509Certificate[] chain 
in your code?

Either it is 1 or iTextSharp is significantly different from iText in this 
respect.

Regards,   Michael.

--
View this message in context: 
http://itext-general.2136553.n4.nabble.com/iTextSharp-and-certificate-chains-using-windows-certificate-store-tp3761613p3765101.html
Sent from the iText - General mailing list archive at Nabble.com.

------------------------------------------------------------------------------
EMC VNX: the world's simplest storage, starting under $10K The only unified 
storage solution that offers unified management Up to 160% more powerful than 
alternatives and 25% more efficient.
Guaranteed. http://p.sf.net/sfu/emc-vnx-dev2dev
_______________________________________________
iText-questions mailing list
iText-questions@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/itext-questions

iText(R) is a registered trademark of 1T3XT BVBA.
Many questions posted to this list can (and will) be answered with a reference 
to the iText book: http://www.itextpdf.com/book/ Please check the keywords list 
before you ask for examples: http://itextpdf.com/themes/keywords.php

***Confidentiality and Security Notice: This message and any attachments are 
intended only for the use of the individual or entity to which it is addressed 
and may contain confidential and/or privileged information. If you are not the 
intended recipient you are hereby notified that any dissemination, copying, or 
distribution of this message, or attachments, is strictly prohibited. If you 
have received this message in error, please notify the sender immediately by 
e-mail and delete it from your computer. Do not send sensitive data via 
unencrypted email as it may be intercepted in transit***




------------------------------------------------------------------------------
EMC VNX: the world's simplest storage, starting under $10K
The only unified storage solution that offers unified management 
Up to 160% more powerful than alternatives and 25% more efficient. 
Guaranteed. http://p.sf.net/sfu/emc-vnx-dev2dev
_______________________________________________
iText-questions mailing list
iText-questions@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/itext-questions

iText(R) is a registered trademark of 1T3XT BVBA.
Many questions posted to this list can (and will) be answered with a reference 
to the iText book: http://www.itextpdf.com/book/
Please check the keywords list before you ask for examples: 
http://itextpdf.com/themes/keywords.php

Reply via email to