Coder Social home page Coder Social logo

Comments (15)

MatthiasValvekens avatar MatthiasValvekens commented on May 21, 2024 1

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.

from pyhanko.

milouk avatar milouk commented on May 21, 2024 1

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

from pyhanko.

MatthiasValvekens avatar MatthiasValvekens commented on May 21, 2024 1

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 :).

from pyhanko.

milouk avatar milouk commented on May 21, 2024

Quick Update:

I used this flag signer_key_usage={'digital_signature'}, and now it works. but Im having an issue with the timestamping. Do you have any idea of what could be wrong? I assume that without timestamping I cant have the document LTV enabled right?

  File "/usr/local/lib/python3.7/site-packages/pyhanko/sign/signers.py", line 2230, in sign_pdf
    timestamper.validation_paths(validation_context)
  File "/usr/local/lib/python3.7/site-packages/pyhanko/sign/timestamps.py", line 150, in validation_paths
    yield validator.validate_usage(set(), {"time_stamping"})
  File "/usr/local/lib/python3.7/site-packages/certvalidator/__init__.py", line 193, in validate_usage
    self._validate_path()
  File "/usr/local/lib/python3.7/site-packages/certvalidator/__init__.py", line 108, in _validate_path
    paths = self._context.certificate_registry.build_paths(self._certificate)
  File "/usr/local/lib/python3.7/site-packages/certvalidator/registry.py", line 320, in build_paths
    missing_issuer_name
certvalidator.errors.PathBuildingError: Unable to build a validation path for the certificate "Common Name: APED Qualified TSU A2 2020, Organization: HELLENIC PUBLIC ADMINISTRATION CERTIFICATION AUTHORITY, Organizational Unit: APED Time-Stamping Services, Country: GR" - no issuer matching "Common Name: APED Global Root CA, Organization: APED, Country: GR" was found

from pyhanko.

milouk avatar milouk commented on May 21, 2024

Thanks for the very quick and detailed reply and for your research as well.

What you proposed indeed worked and I got the document signed but it still shows as "Signature is not LTV enabled" in Adobe. Am I missing something here?

Screenshot 2021-03-14 at 00 17 43

from pyhanko.

MatthiasValvekens avatar MatthiasValvekens commented on May 21, 2024

Hard to tell just from that screenshot, but I'm 90% sure that that's because the TSA authorising the timestamp is untrusted in Acrobat. You can fix that on your own machine by importing the root certificate from earlier into Acrobat's trust store (it's somewhere deep in the settings menu), but that won't necessarily help if you want these signatures to be verifiable by others as well. Regardless, if marking the TSA as trusted makes the signature LTV enabled, then you'll know that that was the problem.

Is there a reason why you have to use this particular TSA? If the platform you're targeting requires this specific TSA I would simply mark the relevant certificate as trusted and move on, but otherwise you might be better off looking for a TSA that is more widely trusted (e.g. one authorised by a certificate authority on the AATL or EUTL).

from pyhanko.

milouk avatar milouk commented on May 21, 2024

So I added it to trusted certificates as you mentioned and now I got this
Screenshot 2021-03-14 at 00 28 39

Is this considered an "LTV enabled" document although the "Rev 1" signature is not LTV enabled?

PS: We are using this TSA as its the Greek Governments official TSA. If we decide that the TSA is the issue here we will most probably contact them to also supply the rest certificates in the chain of trust

from pyhanko.

MatthiasValvekens avatar MatthiasValvekens commented on May 21, 2024

Interesting. Then it could be due to missing revocation information for one of the intermediate certificates, perhaps. Can you send me a signed dummy file at pyhanko.samples <at mark goes here> mvalvekens.be?

Adobe's "LTV" criteria aren't officially documented, so this kind of thing is not always easy to debug.

EDIT: Or perhaps because the TSA's revocation info is itself missing, but the document timestamp is apparently LTV enabled, so that's less likely.

EDIT 2: You can also try debugging with pyHanko's pyhanko sign validate --ltv-profile pades-lta command (supplied with the appropriate trust settings, follow the links here for more info). It should complain if it runs into certificates with incomplete revocation information. If that doesn't detect any problems, try adding --ltv-obsessive.

from pyhanko.

MatthiasValvekens avatar MatthiasValvekens commented on May 21, 2024

Ah, wait, before you try all that: I noticed just now that you didn't add the allow_fetching=True parameter to your validation context. That's another potential reason.

Hmm, perhaps I should have pyHanko log a warning if allow_fetching is False when embedding revocation info...

from pyhanko.

milouk avatar milouk commented on May 21, 2024

Ah, thought about it as I was reading through the ValidationContext declaration but I thought it wouldn't make any difference. Im trying it now.

Edit: Unfortunately, it didn't make any difference, Im sending you the output in your email. Tomorrow morning I am going to try validating via CLI as you proposed.

Thanks again.

EDIT 2:

So I ran pyhanko sign validate --pretty-print --ltv-profile pades-lta --trust '/APEDRoot.cer' out.pdf and got

2021-03-13 23:06:56,826 - pyhanko.sign.general - WARNING - The active key usage policy requires the key extensions non repudiation to be present.
2021-03-13 23:06:56,827 - pyhanko.sign.general - WARNING - Chain of trust validation for "deducted" failed.
==================
Field 1: Signature
==================


Signer info
-----------
Certificate subject: "deducted";
Organization Identifier: deducted;
Organization: deducted"
Certificate SHA1 fingerprint: deducted
Certificate SHA256 fingerprint: deducted
Trust anchor: "No path to trust anchor found."
The signer's certificate is untrusted.


Integrity
---------
The signature is cryptographically sound.
The signature does not cover the entire file.
All modifications relate to signature maintenance, and they appear to be compatible with the current document modification policy.


Signing time
------------
Signing time: 2021-03-13T22:49:38+00:00
The signing time is guaranteed by a time stamping authority.
TSA certificate subject: "Common Name: APED Qualified TSU A2 2020, Organization: HELLENIC PUBLIC ADMINISTRATION CERTIFICATION AUTHORITY, Organizational Unit: APED Time-Stamping Services, Country: GR"
TSA certificate SHA1 fingerprint: d82baeb2f7c86908f42cfbcee52c6e0db391ad09
TSA certificate SHA256 fingerprint: 99ad3e70552851b6cddfe164cfc5d57f92c18c02f1e27d68ffcb5d9912cd957c
TSA cert trust anchor: "Common Name: APED Global Root CA, Organization: APED, Country: GR"
The TSA certificate is trusted.


Seed value constraints
----------------------
There were no SV issues detected for this signature.


Bottom line
-----------
The signature is judged INVALID.

That said there is something probably wrong with the signing certificate eh?

from pyhanko.

MatthiasValvekens avatar MatthiasValvekens commented on May 21, 2024

Ooh, I get it now! I should have read your code more carefully.

You marked the signer's certificate as a trust root in the validation context. This is very likely not what you want: in almost all trust models based on X.509, trust roots are absolute, and in particular things like "revocation status" and so on don't apply to them, so pyHanko doesn't fetch revocation info for trust roots (because that wouldn't make any sense).

You'll want to instead mark the highest relevant certificate in the chain as a trust root here; any intermediates go under other_certs. The signer's certificate doesn't need to be included in the validation context at all.

Fortunately, your cert seems to have been directly issued by a CA on the EUTL ("HARICA Qualified Legal Entities SubCA R3"), so marking that one as a trust root should work.

PS: after writing my previous comment I realised that the CLI won't help you in this case, since there's no way to get rid of the nonRepudiation key usage requirement from the CLI. That's on my roadmap of issues to fix, though.

from pyhanko.

louridas avatar louridas commented on May 21, 2024

Hello Matthias,

First of all thanks (I am also at GRNET where we implement signing / validation services for the Greek public sector). Just a note for the non-repudiation bit. I think it is important to make it configurable, in order for the signatures to be compliant with the ETSI EN 319 412-2, section 4.3.2 (Key Usage) standard; there you can see the permitted combinations of Key Usage settings. The notes are particularly interesting.

In practice, non-repudiation is used with Qualified Electronic Signatures, not with Advanced Signatures.

Best Regards,

Panos.

from pyhanko.

MatthiasValvekens avatar MatthiasValvekens commented on May 21, 2024

Hi Panos,

Thanks for that! I was aware of the difference in semantics between digitalSignatures and nonRepudiation from X.509 / RFC 5280, but I didn't know of this specific call-out in the ESI standard.

Key usage constraints are already fully configurable in the API, but you've convinced me to make getting that into the CLI a priority (esp. for validation). It's not a lot of work---just a matter of exposing the right settings; I should be able to take care of that by the time 0.5.0 is released (which should be soon).

Thanks!

from pyhanko.

inui-sdt2 avatar inui-sdt2 commented on May 21, 2024

Dear Matthias

about signed pdf document validation
I am stucking in "The signer's certificate is untrusted." error(same as above).
I'm sure I'm setting the right one (root and int CA's).
I am also using signer_key_usage={'digital_signature'} at signing stage.

$ python3 verify.py
The active key usage policy requires at least one of the key usage extensions non repudiation to be present.
Chain of trust validation for Common Name: xxxxx failed.

If there are any other possibilities, could you please advise?

root_cert = load_cert_from_pemder('/home/ubuntu/ws/hanko/class1-root-only.crt')
int_cert = load_cert_from_pemder('/home/ubuntu/ws/hanko/intca.crt')
tsa_root_cert = load_cert_from_pemder('/home/ubuntu/ws/hanko/tsa_cacert.pem')

vc = ValidationContext(
    trust_roots=[root_cert],
    other_certs=[int_cert]
    )

ts_vc = ValidationContext(
    trust_roots=[tsa_root_cert]
    )    

with open('signed-13.pdf', 'rb') as doc:
    r = PdfFileReader(doc)
    sig = r.embedded_signatures[0]
    status = validate_pdf_signature(sig, vc, ts_vc)
    print(status.pretty_print_details())

from pyhanko.

BeardOverflow avatar BeardOverflow commented on May 21, 2024

I had the same problem (Signature is not LTV enabled and will expire after xxx) using Sectigo's QTSA server. Fortunately, the comments in this issue helped me to configure the trust root/other certs properly.

trust_root_paths = [
  'ca/sectigo/Sectigo-Qualified-Time-Stamping-Root-R45.crt', # https://crt.sh/?id=3547980726
  'ca/sectigo/Sectigo-Qualified-Time-Stamping-CA-R35.crt', # https://crt.sh/?id=3547998112
]
other_certs_paths = [
  'ca/sectigo/Sectigo-Qualified-Time-Stamping-Signer-3.crt', # https://crt.sh/?id=9297382517
]
trust_roots = [ load_cert_from_pemder(each) for each in trust_root_paths ]
other_certs = [ load_cert_from_pemder(each) for each in other_certs_paths ]

My issue was using Sectigo-Qualified-Time-Stamping-Signer-3.crt as trust_root, but it have to go in other_certs!

from pyhanko.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.