pyHanko: LTV non-repudiation error

Hello Matthias,

First of all great work you have done with pyHanko.

Describe the bug We are planning on using pyHanko on a large scale for signed pdf docs for the Greek public sector. For that we need the signed documents to be LTV enabled. I have tried to make an initial implementation but when I use the param embed_validation_info I get an pyhanko.sign.general.SigningError: ("The signer's certificate could not be validated", InvalidCertificateError('The X.509 certificate provided is not valid for the purpose of non repudiation')) error.

To Reproduce The code I have written so far looks like this

    cms_signer = signers.SimpleSigner.load_pkcs12(
        certificate_filename, passphrase=password.encode('utf-8'))
    
    w = IncrementalPdfFileWriter(pdf_buffer)
    tst_client = timestamps.HTTPTimeStamper('https://timestamp.aped.gov.gr/qtss')

    sv = fields.SigSeedValueSpec(
        reasons=[],
        digest_methods=[],
        flags=3,
    )

    sp = fields.SigFieldSpec('Signature', seed_value_dict=sv, box=(15, 705, 175, 798))

    image = PdfImage(image=settings.STAMP_IMAGE)

    style = TextStampStyle(background=image, border_width=0)
    
    vc = ValidationContext(trust_roots=[cms_signer.signing_cert])
    
    out = signers.PdfSigner(signature_meta=signers.PdfSignatureMetadata(
                                            field_name='Signature',
                                            reason='My reason',
                                            location='My location',
                                            use_pades_lta=True,
                                            subfilter=fields.SigSeedSubFilter.PADES,
                                            embed_validation_info=True,
                                            validation_context=vc
                                            ),
                            signer=cms_signer,
                            timestamper=tst_client,
                            stamp_style=style,
                            new_field_spec=sp
                            ).sign_pdf(w)

Where the certificate_filename is a p12 signing certificate and pdf_buffer is the document I want to sign in BytesIO

Expected behavior In the end I expect a signed document that when opened with Adobe Acrobat Reader it is listed as “LTV enabled”

Screenshots Screenshot 2021-03-13 at 21 50 35

Environment (please complete the following information):

  • Docker with python:3.7 image
  • MacOS 11.2.2

Additional context The same issue exists in both 0.4.0 as well as 0.5.0-dev1

I have contaced HARICA which is the Hellenic Academic & Research Institutions Certification Authority and they told me that non-repudiaton has nothing to do with LTV and it shouldn’t be needed to LTV enable a document.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 15 (7 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @inui-sdt2 !

You need to tell the validator to accept the digital_signature key usage as well. Right now, pyHanko takes a conservative default position by rejecting all signer certificates that don’t have the nonRepudiation/contentCommitment key usage bit set.

You can change that behaviour using the key_usage_settings argument to validate_pdf_signature. See here:

In your case, you probably want to pass in KeyUsageConstraints(key_usage={'digital_signature'}).

I should probably add a few words to the library usage guide to make this part of the API a bit easier to find.


PS: If you have any follow-up questions, could you please create a thread in the discussion space instead? That makes it easier to keep the issue tracker somewhat organised 😃.

Finally, this worked. Matthias thank you very much for your patience and for your help. I learned a lot. Cheers.

Screenshot 2021-03-14 at 01 26 01

Hi milouk, thanks for checking in!

Your first issue is indeed due to the fact that pyHanko (by default) requires signer certificates to have the nonRepudiation key usage bit set. However, some CAs exclusively use the digitalSignature bit instead (whether that’s an appropriate decision is a matter for debate). As a validator it is of course your prerogative to determine which key usages you consider appropriate, so you can override that default (and it seems that you’ve found out how that works, so that’s OK).

As for your second issue: from the error message I’m seeing here, I guess that the time stamping authority that you’re using is not supplying all certificates in its chain of trust. This isn’t a hard requirement of the time stamping protocol, so that sometimes happens. What you can then do is try to track down the relevant certificate(s) yourself, and add them to the ValidationContext you’re using to handle signing/validating. I found a certificate with a subject line that matches the missing one here: http://pki.aped.gov.gr/ca/APEDRoot.crt. Chances are that adding that one to the ValidationContext will do the trick.

Hope this helps, if anything’s still unclear, feel free to ask. 😃

EDIT: The cert I linked is self-signed, so you’ll have to add it to the trusted certificates in the ValidationContext for it to work. Whether you trust that certificate or not is something I can’t decide for you, obviously.