0

I'm trying to set a visible signature on a PDF file with iText7 and BouncyCastle in C#, using a certificate stored on a smartcard. All goes well since I have to create the IExternalSignature object to use in the SignDetached() function of the PdfSigner. At this point I cannot handle to request the PIN code of the Smart Card, so I cannot get the PrivateKey and the signing process fails. How can I do that? Here is a portion of my code:

                X509Store st = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                st.Open(OpenFlags.ReadOnly);
                X509Certificate2Collection col = st.Certificates;
                X509Certificate2 myCert = null;
                X509Certificate2Collection finder = col.Find(X509FindType.FindByTimeValid, DateTime.Now, false);

                X509Certificate2Collection final = new X509Certificate2Collection();
                byte[] firma = new byte[] { 3, 2, 6, 64 };
                foreach (X509Certificate2 xcert in finder)
                {
                    byte[] attrs = GetExtensionValue(xcert, "2.5.29.15");
                    if (attrs != null)
                    {
                        bool add = false;

                        if (attrs.Length == firma.Length)
                        {
                            for (int i = 0; i < attrs.Length; i++)
                            {
                                if (attrs[i] == firma[i])
                                {
                                    add = true;
                                }
                                else
                                {
                                    add = false;
                                    break;
                                }
                            }
                        }

                        if (add)
                            final.Add(xcert);
                    }
                }


                X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(final, "Certificati", "Seleziona il Certificato per Firmare il Documento", X509SelectionFlag.SingleSelection);

                if (sel.Count > 0)
                {
                    X509Certificate2Enumerator en = sel.GetEnumerator();
                    en.MoveNext();
                    myCert = en.Current;
                }
                st.Close();

                DateTime now = DateTime.Now;
                string tmp = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + System.IO.Path.DirectorySeparatorChar + "Temp" + System.IO.Path.DirectorySeparatorChar + "t0.pdf";

                IList<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>();
                X509Chain x509chain = new X509Chain();
                x509chain.Build(myCert);
                foreach (X509ChainElement x509ChainElement in x509chain.ChainElements)
                {
                    chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate));
                }



                Org.BouncyCastle.X509.X509Certificate cert = DotNetUtilities.FromX509Certificate(myCert);
                string contact = string.Empty;
                string name = cert.SubjectDN.GetValueList()[1].ToString();

                PdfReader reader = new PdfReader(inputPDF);
                using (FileStream os = new FileStream(outputPDF, FileMode.Create))
                {
                    PdfSigner signer = new PdfSigner(reader, os, new StampingProperties());

                    StampingProperties properties = new StampingProperties();
                    PdfSignatureAppearance sap = signer.GetSignatureAppearance();
                    sap.SetSignatureCreator("MyProgramSigner");
                    sap.SetRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION);
                    sap.SetReason(!string.IsNullOrEmpty(SigReason) ? SigReason.ToUpper() : string.Empty);

                    sap.SetContact(contact);
                    sap.SetLocation(string.IsNullOrEmpty(SigLocation) ? SigLocation.ToUpper() : string.Empty);

                    sap.SetReasonCaption(string.Empty);
                    sap.SetLocationCaption(string.Empty);
                    StringBuilder sb = new StringBuilder();


                    sb.Append("Documento firmato digitalmente da " + name.ToUpper() + " " + now.ToString("dddd dd/MM/yyyy") + " alle " + now.ToString("HH:mm:ss"));
                    if (!string.IsNullOrEmpty(SigLocation) || !string.IsNullOrEmpty(SigReason))
                        sb.AppendLine();
                    if (!string.IsNullOrEmpty(SigReason))
                        sb.Append("Motivo della firma: " + SigReason.ToUpper());
                    if (!string.IsNullOrEmpty(SigLocation) && !string.IsNullOrEmpty(SigReason))
                        sb.Append("; ");
                    if (!string.IsNullOrEmpty(SigLocation))
                        sb.Append("Luogo Firma: " + SigLocation.ToUpper());

                    sap.SetLayer2Text(sb.ToString());

                    iText.IO.Image.ImageData img = iText.IO.Image.ImageDataFactory.Create(Properties.Resources.pdf_signatureLogo, null, false);

                    sap.SetImage(img);
                    sap.SetImageScale(.5f);

                    AffineTransform af = new AffineTransform();
                    af.Rotate((float)(Math.PI / 180) * angle);



                    Rectangle rect = new Rectangle(x, y, w, h);
                    sap.SetPageRect(rect);
                    sap.SetPageNumber(_page);

                    signer.SetSignDate(now);
                    sap.SetSignatureGraphic(sap.GetImage());
                    sap.SetCertificate(cert);

                    signer.GetDocument().GetCatalog().SetModified();


                    IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256); // what is pk? I don't know, tried many things, but none worked...
                    signer.SignDetached(pks, chain.ToArray(), null, null, null, 0, PdfSigner.CryptoStandard.CMS);


                    return true;
                }
The Agony
  • 138
  • 1
  • 8
  • *"I cannot handle to request the PIN code of the Smart Card"* - why not? Smart cards are designed to require PINs... – mkl Jun 14 '20 at 21:18
  • I don't know how to request the pin, in cades cryptography bouncycastle does it all by itself, but how to do it for pades signing? – The Agony Jun 15 '20 at 11:38
  • Have you already checked [this answer](https://stackoverflow.com/a/50627944/1729265) to a related question? – mkl Jun 16 '20 at 16:24
  • 1
    already checked but last time I implemented it in the wrong way (XD), now it seems to work, thanks! – The Agony Jun 16 '20 at 19:58
  • Great! I'll close your question as duplicate of that question then. – mkl Jun 17 '20 at 05:01

0 Answers0