0

I am adding a digital signature to a pdf using Itextsharp, which is being added perfectly. But now I need to add that digital signature in a box.

I tried the below things:- 1) created a textform field in a rectangle and tried to replace the form field with a digital signature, but did not happen as it does not recognise it as a signature field. (IDK what it actually means)

2) When I open the pdf in adobe I can see a rectangular box flicker on hover of the signature. No verification needed.

But i need the signature in the box.

My code after adding the changes from @mkl's answer:

PdfReader reader1 = new PdfReader(this.inputPDF);
PdfStamper st = PdfStamper.CreateSignature(reader1, new FileStream(this.outputPDF, FileMode.Create, FileAccess.ReadWrite), '\0');
AcroFields pdfFormFields = st.AcroFields;
st.SetEncryption(PdfWriter.STRENGTH40BITS, null, null, PdfWriter.AllowPrinting);
st.MoreInfo = this.metadata.getMetaData();
st.XmpMetadata = this.metadata.getStreamedMetaData();

PdfSignatureAppearance sap = st.SignatureAppearance;
sap.SignDate = Convert.ToDateTime(DateTime.Now.ToLocalTime()); 
sap.Layer2Font = new Font(Font.HELVETICA, 12, Font.BOLD);
sap.Layer2Text = "Digitally Signed \nVICE PRESIDENT- \nDate:" + ; //+ "\nLocation: BENGALURU";
sap.SetCrypto(this.myCert.Akp, this.myCert.Chain, null, PdfSignatureAppearance.SELF_SIGNED);
sap.Contact = SigContact;
sap.Location = SigLocation;
Rectangle obj = new iTextSharp.text.Rectangle(75, 90, 600, 300);
sap.SetVisibleSignature(obj, 1, "sig");

sap.GetAppearance();
PdfTemplate layer20 = sap.GetLayer(2);
Rectangle rectangle = sap.Rect;
layer20.SetRGBColorStroke(0, 0, 0);
layer20.SetLineWidth(5);
layer20.Rectangle(00, 80, 250, 100);
layer20.Stroke();

st.close();

Currently using 5.5.13.

Moreover, I get an error DER length is more than 4 bytes while hosting it on server with SSL certificate.

Stack trace for the same.

`System.IO.IOException was caught
  HResult=-2146232800
  Message=DER length more than 4 bytes: 32
  Source=itextsharp
  StackTrace:
       at Org.BouncyCastle.Asn1.Asn1InputStream.ReadLength(Stream s, Int32 limit)
       at Org.BouncyCastle.Asn1.Asn1InputStream.ReadObject()
       at Org.BouncyCastle.Asn1.Asn1InputStream.BuildEncodableVector()
       at Org.BouncyCastle.Asn1.Asn1InputStream.BuildDerEncodableVector(DefiniteLengthInputStream dIn)
       at Org.BouncyCastle.Asn1.Asn1InputStream.CreateDerSequence(DefiniteLengthInputStream dIn)
       at Org.BouncyCastle.Asn1.Asn1InputStream.BuildObject(Int32 tag, Int32 tagNo, Int32 length)
       at Org.BouncyCastle.Asn1.Asn1InputStream.ReadObject()
       at Org.BouncyCastle.Asn1.Asn1InputStream.BuildEncodableVector()
       at Org.BouncyCastle.Asn1.Asn1InputStream.BuildDerEncodableVector(DefiniteLengthInputStream dIn)
       at Org.BouncyCastle.Asn1.Asn1InputStream.CreateDerSequence(DefiniteLengthInputStream dIn)
       at Org.BouncyCastle.Asn1.Asn1InputStream.BuildObject(Int32 tag, Int32 tagNo, Int32 length)
       at Org.BouncyCastle.Asn1.Asn1InputStream.ReadObject()
       at Org.BouncyCastle.Asn1.Asn1Object.FromStream(Stream inStr)
       at Org.BouncyCastle.Pkcs.Pkcs12Store.Load(Stream input, Char[] password)
       at Org.BouncyCastle.Pkcs.Pkcs12Store..ctor(Stream input, Char[] password)
       at Letters.Models.PDFSigner.Sign(String SigReason, String SigContact, String SigLocation, Boolean visible, String strType, String path, String password) in :line 93`

Edited code sharing again, Please help me find if there is some error in it.

Stream path1 = new FileStream(path, FileMode.Open, FileAccess.Read);

      Pkcs12Store pk12 = new Pkcs12Store(path1, password.ToCharArray());
        path1.Dispose();

        //then Iterate throught certificate entries to find the private key entry
        string alias = null;
        foreach (string tAlias in pk12.Aliases)
        {
            if (pk12.IsKeyEntry(tAlias))
            {
                alias = tAlias;
                break;
            }
        }
        var pk = pk12.GetKey(alias).Key;


        PdfReader reader = new PdfReader(this.inputPDF);
        FileStream os = new FileStream(this.outputPDF, FileMode.Create);
        PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
        PdfSignatureAppearance appearance = stamper.SignatureAppearance;
        appearance.Layer2Font = new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD);`
Richa Sharma
  • 3
  • 1
  • 7
  • If you need a special appearance of the signature, you can completely design the appearance yourself. Simply retrieve layer 2 and put content onto it as you desire. – mkl Feb 20 '18 at 06:30
  • Please elaborate the response. Currently I am just able to set layer2font and layer2text. – Richa Sharma Feb 20 '18 at 08:03
  • If you have additional relevant information (like the stack trace), *do share it!* If the stack trace is still [the same](https://i.stack.imgur.com/KjSBz.png) as in that other, now deleted answer, consider the comment I left there: There is no *iText* class involved in it, but `HomeController` in `DownloadFile` attempts to `Combine` two paths one of which contains an `Illegal character`. In that case, therefore, also share the `DownloadFile` method and log the paths you attempt to combine when the error is thrown. – mkl Mar 08 '18 at 13:47
  • Considering the edit: Ok, now that you use iText 5.5.13, the solution from my answer should work as desired. Does it? Does it not? In the latter case do describe the expected behavior and the observed behavior, using screenshots where applicable. – mkl Mar 08 '18 at 13:51
  • I was trying my way around it but could not find the value of parameters in below code `IExternalSignature pks = new PrivateKeySignature(parameters, DigestAlgorithms.SHA256);` no ICipherParameters defined by me. Also, I dont have a private key. I just have a pfx file that I am accessing with a password. no encrytion or decryption. – Richa Sharma Mar 09 '18 at 09:39
  • Cf. [this answer](https://stackoverflow.com/a/2292591/1729265), a pfx file can contain a private key, and in your case it must do so because signing requires a private key. That being said, when I'm at my desktop computer again next week I'll try and post how to open the p12 file. – mkl Mar 11 '18 at 08:12
  • Thanks a ton mkl.. – Richa Sharma Mar 12 '18 at 05:24
  • Now that everything works fine @mkl , I get error in below line `Pkcs12Store pk12 = new Pkcs12Store(path1, password.ToCharArray());` Stack trace is as mentioned above. – Richa Sharma Mar 13 '18 at 09:38
  • The p12 file probably is not in a format bouncy castle (the security library used by iText) can read. It expects it in binary format, not in base64 encoded text form. Alternatively the password may be wrong. – mkl Mar 13 '18 at 10:22
  • It works fine in my system but throws error in a server which already has an SSL certificate installed.I hope there is no link between the pfx file and SSL – Richa Sharma Mar 13 '18 at 11:18
  • and it has something like this defined `public Pkcs12Store(Stream input, char[] password);` So currently I am passing it as `Pkcs12Store pk12 = new Pkcs12Store(path1, password.ToCharArray());` where path1 is defined as `Stream path1 = new FileStream(path, FileMode.Open);` – Richa Sharma Mar 13 '18 at 11:24
  • If it works fine on your machine but not on the server, then there are differences. E.g. the iTextSharp version may differ, an older version often includes an older BouncyCastle version which might not yet be able the file format. Or the p12 itself might be different. Or or or... you have to compare. – mkl Mar 13 '18 at 12:41
  • It is the same version :( – Richa Sharma Mar 13 '18 at 12:55
  • are the p12 files identical? – mkl Mar 13 '18 at 13:05
  • Probably it wasnt. Because Whn I took recent PKCS12Store.cs from google , code stopped working in my machine too . :/ – Richa Sharma Mar 13 '18 at 13:18
  • I never thought it could be too time consuming – Richa Sharma Mar 13 '18 at 13:19
  • *"PKCS12Store.cs from google"*? The `PKCS12Store` class in question is in the namespace `Org.BouncyCastle.Pkcs` bundled in iTextSharp. You probably should use the classes that were meant to be used... – mkl Mar 13 '18 at 13:32
  • *"Edited code sharing again, Please help me find if there is some error in it."* - first of all, do you still experience the same exception as above or did you share this specific piece of code because of other unwanted observations? – mkl Mar 14 '18 at 07:56
  • Hi @mkl, the issue is resolved now. I deleted all the references and added again . same with the pfx file and it worked. – Richa Sharma Mar 17 '18 at 05:35
  • So in addition to my answer you only needed to clean up project references? – mkl Mar 19 '18 at 13:31
  • Yes @mkl, thank you :) – Richa Sharma Mar 21 '18 at 04:30
  • Great! Please also mark the answer as accepted answer (click the tick at its upper left). – mkl Mar 21 '18 at 06:32

1 Answers1

1

When you sign a PDF using iText 5.5.x, you usually do something like

// Creating the reader and the stamper
PdfReader reader = new PdfReader(SRC);
FileStream os = new FileStream(DEST, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');

// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = "Test customized appearance";
appearance.Location = "Singularity";
appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");

// Creating the signature
IExternalSignature pks = new PrivateKeySignature(parameters, DigestAlgorithms.SHA256);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CADES);

You can freely customize the visual appearance by working on the layer templates after the appearance.SetVisibleSignature call, e.g. like this:

// trigger creation of default layers contents
appearance.GetAppearance();

// Customize the layer contents
PdfTemplate layer2 = appearance.GetLayer(2);
Rectangle rect = appearance.Rect;
layer2.SetRGBColorStroke(255, 0, 0);
layer2.SetLineWidth(2);
layer2.Rectangle(rect.Left, rect.Bottom, rect.Width, rect.Height);
layer2.Stroke();

to draw a red line along the signature appearance border

mkl
  • 90,588
  • 15
  • 125
  • 265
  • Hey, Thank you :) I get the box now. But signature disappeared. – Richa Sharma Feb 20 '18 at 12:44
  • Please look at the code addition in my answer, in particular the line after the comment `// trigger creation of default layers contents`. That line is necessary if you want to add to the default appearance (in contrast to create the appearance completely yourself). You seem to have forgotten to copy it. – mkl Feb 20 '18 at 13:06
  • `Rectangle obj = new iTextSharp.text.Rectangle(75, 15, 800, 300); sap.SetVisibleSignature(obj, 1, null); PdfTemplate layer20 = sap.GetLayer(2); Rectangle rectangle = sap.Rect; layer20.SetRGBColorStroke(255, 0, 0); layer20.SetLineWidth(2); layer20.Rectangle(50, 50, 50,50); layer20.Stroke();` This is my code as of now – Richa Sharma Feb 20 '18 at 13:07
  • Thank you for your help till now mkl. One more question, now I can see a "Question mark" along with "Signature not verified" message. How can I work on it.? – Richa Sharma Feb 21 '18 at 04:57
  • Please help in below scenario. I am digitally signing a pdf using c# and itextsharp. Currently, along with the digital signature, i am able to see a question mark, a thumbnail image and an Invalid msg with the same. Is there any link where I can understand about the same or any help to remove it or set the location and specifically hide the image. – Richa Sharma Feb 21 '18 at 12:23
  • Have you by chance set `Acro6Layers` to `false`? – mkl Feb 21 '18 at 14:16
  • No, its set to true only. – Richa Sharma Feb 22 '18 at 04:21
  • Please don't add that much code in comments. Edit it into your question (there is an "edit" link right underneath it) and refer to that edit in a comment. I edited your code into your question for you this time. – mkl Feb 22 '18 at 11:39
  • That being said there appear to be errors in your code. The `sap.Layer2Text = ...` line obviously is syntactically wrong. – mkl Feb 22 '18 at 11:47
  • You in particular appear not to use a current 5.5.x (or 7.x) version of iText but instead probably some 4.1.x version. The signature API changed quite a bit since then. My answer (as mentioned in it) uses a current 5.5.x. Furthermore, signatures that old iText creates for `PdfSignatureAppearance.SELF_SIGNED` are deprecated with PDF 2.0. I'd recommend updating your iText to the current 5.5.x or (if you can afford following up to a complete API re-design) even better 7.1.x – mkl Feb 22 '18 at 12:08
  • Actually, it allows to add only Reason, Contact and location elsewise whereas I need another data in signature. Hence used Layer2Text. Could you please help me with where to refer for complete understanding or my errors. – Richa Sharma Feb 22 '18 at 12:27
  • It is not possible to change the version of iTextSharp. Currently using 4.1.2. – Richa Sharma Feb 22 '18 at 12:28
  • Sorry, I'm not proficient in that ancient version (anymore). – mkl Feb 22 '18 at 12:35
  • Any reference link that could help me with it? – Richa Sharma Feb 22 '18 at 12:38
  • Unfortunately no. When I worked with iText/Java 2.1.x (which corresponds with iTextSharp 4.1.x), my interests concerning that library were very focused on a specific use case, and what you're after is beyond that. I would recommend retrieving the old iTextSharp code and analyzing it. – mkl Feb 22 '18 at 12:43
  • Thank you for all the help :) – Richa Sharma Feb 22 '18 at 13:10
  • Hi Mkl, Now that I am using iTextSharp version 5.5.13. Would like if you could help me solve the issues. Also, I am facing the error "DER length is more than 4 bytes" while hosting it on server with SSL certificate. Please help on this. – Richa Sharma Mar 08 '18 at 06:39
  • @RichaSharma Concerning *"Also, I am facing the error "DER length is more than 4 bytes" while hosting it on server with SSL certificate."* - We saw that that is no iText issue at all, cf. [this comment](https://stackoverflow.com/questions/49103370/der-length-more-than-4-bytes-itextsharp-error-while-hosting-on-server#comment85269735_49103370) to ["DER Length more than 4 bytes - itextsharp error while hosting on server"](https://stackoverflow.com/q/49103370/1729265). – mkl Mar 08 '18 at 10:58
  • @RichaSharma Concerning *"Would like if you could help me solve the issues. "* - Please clearly explain which issues you mean exactly. With all these comments here it is not clear which issues remain and which were 4.1.x related only. And please don't do so in comments but instead either edit the question here, show your current code and list all issues you still have. Or create a new question to clearly show the current situation. – mkl Mar 08 '18 at 11:03
  • That question is deleted now. All my questions are same as above edited post. – Richa Sharma Mar 08 '18 at 11:32
  • I want to note important thing for a beginner like me: Let customize the layer contents before creating the signature. Thank @mkl for your solution! – ThanhLD Nov 01 '18 at 03:36
  • @ThanhLD *"customize the layer contents before creating the signature"* - correct, by "after the `appearance.SetVisibleSignature` call" i meant *immediately* after that call which is in particular before the `MakeSignature.SignDetached` call. – mkl Nov 01 '18 at 08:46