0

I've read the I-TEXT digital signature e-text, and also previous posts answered by MKL (who seems to be the authority along with Bruno on this topic).

essentially I have an Azure app service that gets the digital sig (base 64) and certificate chain from the company's signing API. The company's signing API returns a signature in Base64 along with a certificate chain.

I just want the to insert a signature object/container into the pdf so it will show in the signature panel when an end user opens up the pdf. I prefer to use deferred signing.

I've shifted from chapter 4's "clientseversigning example" to instead Deferred Signing in MKL's "How to create a PDF signature without knowing the signer certificate early".

The Company API returns a "plain" signature, that I am pretty sure, and also returns a chain of 3 string certificates.

I should note I do have the root and sub certs in advance (2 .cer files) but I am not using them in "prepping" the pdf for hashing right now since the deferred signing example doesn't make use of them obviously. For the container construction code (after getting the response from the Company API), I use the 3 certs chain returned from the company API, but I also tried it with the 2 .cer files, to no avail.

The only difference between my code and the one in the example is instead of byte[] certificateBytes = THE_RETRIEVED_CERTIFICATE_BYTES; X509Certificate x509Certificate = new X509CertificateParser().ReadCertificate(certificateBytes); I build 3 x509Certificates (one for each string in the chain returned from the Company API.

Sadly things wont work, I get these errors in Acrobat: Signature is invalid, There are errors in the formatting or information contained in this signature, signature's identity has not yet been verified, signing time is from the clock on the signer's computer...also if I click Certificate details just below of this error in Acrobat it is blank. This was pretty much the errors I was getting when trying the "clientserversigning example"

I am trying really hard and wondering what it could be... should I try modifying the estimated size from 12000 and bump it up? or the errors I am getting in Acrobat, maybe they are hinting the certificate chain from the Company API is not being picked up by the signing deferral container construction code ... I am struggling but any tips would be so greatly appreciated

Evan


Just to clarify, I am following chapter 4's clientserversigningexample but I am getting the following once my pdf is recreated with the signature from the company API

resulting pdf not correctly signed

Its saying 1) there are errors in the formatting of information 2) signer's identity has not been verified 3) signing time is from the clock on the signer's computer

now as far as "prepping" the pdf before hashing it to send for signing...I don't see anything in the ClientSigning example that specifically preps it, can I assume the IText library is prepping it under the hood?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • **a**) the PDF has to be prepared before hashing the byte ranges to be signed (which is *not* the whole prepared PDF!); **b**) whether it suffices to get the certificate only together with the signature, depends on the format the signature is returned in. If the company API returns a CMS signature container, you don't need the certificate before; if it's a plain signature, usually the certificate is required beforehand. – mkl Jul 11 '20 at 20:47
  • *"should I look at PDFBox instead of Itext"* - you have indicated no special requirements for your signature (e.g. you mention no special profile to create like PAdES-LTA), so either library should do. – mkl Jul 11 '20 at 20:57
  • github is down, but this woman has solutions for several pdf libraries: https://github.com/crs2195/ – Tilman Hausherr Jul 13 '20 at 08:01
  • thanks mkl, suffice to say you're the authority on this stuff; I think its a plain signature the company API returns...I'm reading over all the texts...is it safe to assume if I don't have access to the certificates beforehand than I would use the deferred singing example and if I did have the certificates beforehand I would use the clientserversigningexample? In other words I'm having difficulty distinguishing between these two ... but I guess if the company API only returns the plainsignature (with a chain of certs mind you) it forces my hand and I have to use the clientseversigningexample? – Evan Econo Jul 13 '20 at 19:00
  • just an addendum, I do have two certificates from the company API, root and sub, both are .cer files. Is it safe to assume I can create a chain using these two certs when building the call to the company api using the clientserversigningexample? Is the chain return value the company API returns any different would you think? – Evan Econo Jul 13 '20 at 19:16
  • is it just me or in IText7 you can't instantiate a PDFReader from a byteArray like you could in ITextSharp....guess they don't make them like they use to ...any workaround ? – Evan Econo Jul 14 '20 at 00:01
  • *"can't instantiate a PDFReader from a byteArray"* - not directly. But you can do `new PdfReader(new RandomAccessSourceFactory().CreateSource(YOUR_BYTE_ARRAY), new ReaderProperties())`. – mkl Jul 14 '20 at 13:36
  • thanks man, this helps more than you know, I guess I need to know if using clientserversigning example is the way to go or if I should do the deferred signing example – Evan Econo Jul 14 '20 at 13:38
  • which one is more appropos? – Evan Econo Jul 14 '20 at 13:56
  • well looks like I answered my own question possibly...looking at the c# IText examples, the deferred signing example requires the private key ICipherParameters pk = pk12.GetKey(alias).Key; and I know I don't have access to a private key so I will stick with Client Server Signing Example – Evan Econo Jul 14 '20 at 14:32
  • *"is it safe to assume if I don't have access to the certificates beforehand than I would use the deferred singing example and if I did have the certificates beforehand I would use the clientserversigningexample"* - No. Strictly speaking, unless one can get away with very primitive signatures in one's use case, one needs the certificate before doing the actual signing call. Whether or not to use deferred signing is a different matter. I'll write an answer focusing on this. – mkl Jul 14 '20 at 14:38
  • thanks man, I'm looking over your exchanges with "Always Developer" on https://stackoverflow.com/questions/58486468/digital-pdf-document-signing -> I noticed in your example you provided it tries it without a certificate beforehand...I'm thinking of giving that a try but with a PKCS7 not a PKCS1 If needbe, I have access to the root and sub .cer files beforehand-> is it easier this way? oddly though the company API returns 3 certificates so I'm not sure where the discrepancy lies. – Evan Econo Jul 14 '20 at 15:33
  • Please take the time to read [ask]. Questions should contain one, complete, self-contained question that has all of the information necessary for someone to provide an answer, not just for you, but future visitors to the site who might have the same problem. Any additional information that you think of should be added to the question by means of the [edit] button, but it should relate to a single question. If you solve that and move on to a different question, you should raise it as a separate question and consider accepting the answer that has helped you best on this one. – David Buck Jul 15 '20 at 11:55
  • Not a problem, I've edited the question; – Evan Econo Jul 15 '20 at 12:16

1 Answers1

0

In your question and in your comments to it you appear to be in particular interested in

  • whether or not one can use a signature API that returns the certificates only together with the signature, and
  • when to to deferred signing.

Can You Use a Signature API That Provides the User Certificate Only After Signing

To answer this one first has to clarify what kind of signatures the signature API in question creates, plain signature values (e.g. PKCS#1 RSA signatures) or full-fledged CMS signature containers.

If it creates full-fledged CMS signature containers, you can create signatures following arbitrary signature profiles as long as the signature containers follow the requirements for them (which they often do). They only restriction you have is that you cannot have information from the signer certificate in the signature visualization because that visualization is defined in the signed data of the PDF.

If it only creates plain signature values, the best you can do is create and embed simple CMS containers that don't contain pointers to the signer certificate in the signed attributes (if they have any signed attributes as all to start with). Many signature policies of interest do require such pointers, but at least Adobe Reader accepts signatures without.

If you are in this situation and want to try creating signatures with such simple signature containers, you may want to use the code from this answer, section "How to create a PDF signature without knowing the signer certificate early".

When to Use Deferred Signing

The difference between deferred signing and other iText signing calls is not that deferred signing requires less information (compared to ExternalContainer signing).

In contrast to the other iText signing methods, signDeferred re-uses the outermost existing, filled signature field of the PDF to sign and merely replaces the signature container therein.

The method name is derived from the most common use case it’s used for:

  • In a first step a signature field is (probably first created and then) filled using signExternalContainer with an IExternalSignatureContainer implementation that calculates the document hash to be signed but does not return the final CMS container yet, merely some (usually) empty array. The generated PDF with a filled signature field (albeit without the final signature container) is then temporarily stored (in the file system or a database).
  • In a second step a signature container for the determined document hash is requested and (probably asynchronously) awaited.
  • In a final step signDeferred is used to inject the retrieved signature container into the PDF prepared in the first step.

This deferred signing process usually is preferred in setups in which the second step, the signature container creation and retrieval, can take longer than one wants to keep the resources blocked which are required for the document in signing. This includes in particular signatures generated by remote servers or clients, especially if that signing process awaits some third party clearance or activation.

mkl
  • 90,588
  • 15
  • 125
  • 265
  • hi mkl, I can't thank you enough...is there a way to distinguish or know whether the returned signature from the company API is a plain signature or full fledged CMS signature container by inspecting/looking at the base64string "signature" it returns? can I make an informed guess? – Evan Econo Jul 14 '20 at 22:02
  • followed "this answer" code example...I'm still getting the "signed by unknown" / signer's identity has not yet been verified error in the signature panel......I'm wondering if its somehow related to where you talk about: – Evan Econo Jul 14 '20 at 22:15
  • "A CMS signature container can contain a structure of "signed attributes". If it does, one of these attributes must be the hash of the signed PDF bytes (see above, everything but the Contents value) and the actual signature bytes wrapped in the container sign these signed attributes. Whether the variant without signed attributes is allowed and which attributes additionally are required, depends on the exact type of the signature." – Evan Econo Jul 14 '20 at 22:15
  • *"can I make an informed guess?"* - well, already the size is a hint. Less than 1KB is most likely a naked signature. More than 2KB is most likely a bigger structure like a CMS signature container. – mkl Jul 14 '20 at 23:10
  • ah in that case it looks like its a naked signature...I copied/pasted the signature it returned, and the notepad file came in at 344bytes...mind you this is following your "How to create a PDF signature without knowing the signer certificate early". – Evan Econo Jul 15 '20 at 01:34
  • in your example with AlwaysDeveloper you mentioned "For the hash calculated above in the Hash variable you can now request a PKCS#1 signature and the signer certificate." ...can or should I request a PKCS7 instead? maybe its a stretch but I'm at a loss as to why things won't work – Evan Econo Jul 15 '20 at 01:35
  • If you can request a pkcs7... a pkcs7 essentially is a cms signature container! – mkl Jul 15 '20 at 05:02
  • I should have clarified, my mistake it was late last night, I 'm pretty sure that -company API returns a "plain" signature because its manual says I have to create the signature object myself and also due to the small size (~350bytes) - returns a chain of certificates which when I tried it had a chain of 3 signature strings returned though the company provided me with 2 cer files in advance (a root and sub) so I don't know why there would be 3 returned – Evan Econo Jul 15 '20 at 11:02
  • p.s. I am struggling...should I bump up the estimated size from 12000? the errors I am getting in Acrobat, maybe they are hinting the certificate chain from the Company API is not being picked up by the signing deferral container construction code. as an aside, I am assuming the ExternalHashingSignature Container takes care of the "prepping" of the hash /determines the proper hash of the byte ranges. I say assume because I don't see an explicit call to getAuthenticatedAttributeBytes? I do see return new byte[0] in ExternalHashingSignatureContainer which is a dummy/empty value for some reason? – Evan Econo Jul 15 '20 at 12:22
  • The only difference between my code and the one in the example is instead of byte[] certificateBytes = THE_RETRIEVED_CERTIFICATE_BYTES; X509Certificate x509Certificate = new X509CertificateParser().ReadCertificate(certificateBytes); I build 3 x509Certificates (one for each string in the chain returned from the Company API. – Evan Econo Jul 15 '20 at 12:30
  • looks like the "mystery" 3rd certificate the CompanyAPI returns is the cert with the private key used to generate the signature...so I have root, sub and this third one. should I or shouldn't I use this 3rd one in the cms container construction code from" How to create a PDF signature without knowing the signer certificate early example" – Evan Econo Jul 15 '20 at 12:40
  • Chances are that the third certificate is the signer certificate. In that case that's the certificate you eventually need to fill in some details. – mkl Jul 15 '20 at 13:06
  • ah ok so can I use that cert exclusively in the byte[] certificateBytes = THE_RETRIEVED_CERTIFICATE_BYTES; part of the "How to create a PDF signature without knowing the signer certificate early example" ? In other words I can forget about the other two certs (root and sub) – Evan Econo Jul 15 '20 at 13:58
  • That's what I'd assume. (You have not provided any example data yet, so I have to guess a lot...) – mkl Jul 15 '20 at 14:02
  • :) some small glimmer of hope, now the pdf , though while still having a signature invalid error, at least picks up the signer's correct name "signed by". the errors now are: 1)- document has been altered or corrupted since it was signed 2)- signer's identity is unknown because it has not been included in your list of trusted certificates and this annoying one 3)- signing time is from the clock on the signer's computer – Evan Econo Jul 15 '20 at 14:26
  • I know I have trusted the root and cert already in my list of trusted certs so maybe I shouldn't forget about root and sub certs in my code when it signs the pdf? – Evan Econo Jul 15 '20 at 14:27
  • *root and sub certs* - as you do have them, you should also add them to the signature container. In the code of the referenced answer there is an `Asn1EncodableVector certs` to which the signer certificate `x509Certificate` is added (`certs.Add(x509Certificate.CertificateStructure.ToAsn1Object())`). Simply analogously add the other relevant certificates you have to this `Asn1EncodableVector`. – mkl Jul 15 '20 at 15:10
  • I wanted to thank you again mkl, you were right, looks like it was the signer's certificate I needed and not the other two – Evan Econo Jul 15 '20 at 16:42