Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Code Signing Certificates to x509.verification #12464

Open
loewexy opened this issue Feb 15, 2025 · 10 comments
Open

Support for Code Signing Certificates to x509.verification #12464

loewexy opened this issue Feb 15, 2025 · 10 comments
Labels
Stale waiting-on-reporter Issue is waiting on a reply from the reporter. It will be automatically cloesd if there is no reply.

Comments

@loewexy
Copy link

loewexy commented Feb 15, 2025

I want to use cryptography to validate a certificate chain of a signing certificate. But the x509.verification can only support server and client certificates.

Did I miss anything, or is there a work around to get that working. For a first step it would be okay for me to just validate the certificate chain to a root. The check if the leaf certificate has the correct KU and EKU can be done manually, but Path validation is tedious and error prone to implement myself.

@alex
Copy link
Member

alex commented Feb 15, 2025

With #11165 merged, it is possible to set custom extension policies.

A code signing cert is a form of client verification (you're not checking that a cert is valid for a particular name, you're looking which names its valid for).

@alex alex added the waiting-on-reporter Issue is waiting on a reply from the reporter. It will be automatically cloesd if there is no reply. label Feb 15, 2025
@loewexy
Copy link
Author

loewexy commented Feb 15, 2025

Okay that seems interesting and I can imagine that this could work. But the documentation currently leaves me puzzled about how to use it.

  • Maybe an Example on how to use a custom Extension Policy would be helpful in the documentation. Because understanding how the different components play together is very hard. Other parts of cryptography have a guide that will deliver the basic understanding of the concepts.
  • The point that a client verifier can be used more general could be explained more. I re-read the documentation but I still can not understand what is the difference and when to use what, apart from the two use cases client or server cert validation.
  • Also for me it is not clear why the PolicyBuilder and the Policy have different properties. The Policy seems to have a EKU constraint, which can not be set by the Builder (and why is there a seperate field for exactly that extension?). Also the store and extension policy that is given to the builder is no property of the Policy. Maybe the documentation is just not complete?

If I understand this correctly this is in the current development version but not in a released version? Is there a beta version available on pypi? If not is there some sort of release cycle where I can check when this will be in a release?

However, thanks for your work on this library, it makes my life so much easier. And I can currently see many new features being worked on which are helpful in making cryptography the only library required for any cryptographic topics.

@reaperhulk
Copy link
Member

reaperhulk commented Feb 15, 2025

That's correct, this is in main only and not in a released version at this time. You can install the project from source or pull a wheel from a recent wheel builder CI job(like https://github.com/pyca/cryptography/actions/runs/13346680907) if you'd like to test the new APIs prior to release. We welcome documentation improvements based on user experiences!

@loewexy
Copy link
Author

loewexy commented Feb 15, 2025

Unfortunately I need this feature at a work project, but I can not use unreleased packages in our productive code base. Depending on when it will be released I would have to implement a some work around until it ships, or I can just wait for the release to happen.

There is no possibility to have a work around that ignores the KU and EKU with the code in version 44 or? The check on the extension of the ee can then by done manually.

If I manage to understand the things which I mentioned above, I may be able to contribute documentation. But I have to understand it first.

@deivse
Copy link
Contributor

deivse commented Feb 17, 2025

For examples on how the ExtensionPolicy API can be used, you can reference the tests, for example this one:

def test_require_present(self):

There are two main differences between a ClientVerifier and a ServerVerifier:

  1. A ServerVerifier is built with a specific subject, and the verification will fail if the certificate doesn't contain a SAN extension which matches the subject specified in build_server_verifier. So this is intended to be used when you know who the certificate must belong to, which is the case when connecting to a server via https. In many other cases you don't know the subject in advance. Then ClientVerifier can be used, which doesn't require that the SAN extension contains a specific value.
    Despite not knowing the exact subject, you may still have eg. a whitelist of possible subjects, and after calling ClientVerifier.verify, you can access the subjects from the SAN extension via VerifiedClient.subjects.

  2. The default EE extension policies check the EKU extension. For ClientVerifier, it is required to have the ClientAuth EKU, and for ServerVerifier, ServerAuth. The EKU is not currently user configurable (although this may be exposed later via a method on PolicyBuilder), however you can create a custom extension validator callback and use a custom extension policy that will constrain the EKU in any way you want.

Why some properties are on Policy but not on PolicyBuilder

The current Policy class is basically a direct mapping to python from a rust struct that contains context required for chain building and certificate verification/validation. The main purpose of the Policy class is to expose this context to python extension validation callbacks (as set by ExtensionPolicy.may_be_present and similar methods) so that the callbacks can express complex constraints based on these parameters. There wasn't really a per-property decision process on whether to include something there or not, but I don't think it hurts to have extra stuff there since we can't envision every use case. Some of these properties, for example, EKU, as you have noted, can not yet be configured by the user. However they can still be useful, for example you might want to write a verification callback for another extension that makes a decision based on what EKU value is required by the policy.

You are right that this might be a bit confusing currently, and there is a slight leakage of implementation details into the public API. However this could not be reasonably avoided currently I would say, and I would err on the side of the Policy class providing access to extra properties rather than trying to predict every use case. Maybe there's something to be said about the naming - there is a clear parallel between PolicyBuilder and Policy, but, as @loewexy said, not all properties configurable via the builder are accessible on Policy and vice versa. I don't have any good ideas on how to improve this currently, but maybe we can come up with a better name for Policy

@deivse
Copy link
Contributor

deivse commented Feb 17, 2025

Oh yeah, and regarding having the extension policies or the store as properties on Policy:

  1. For the extension policies, I don't see a strong use case currently, and it would require creating a mapping from rust to python (which currently is only the other way around), which is not something you want to do, trust me 😄
  2. The store is not really part of the Policy, since it's potentially specific to verifying a single certificate, whereas a policy (conceptually here, not necessarily the Policy class) can be used to verify any number of certificates issued by different CAs.

That second point brings me to a renaming idea, which might actually make sense, but it's a breaking change unfortunately - instead of renaming Policy it would maybe make more sense to rename PolicyBuilder to something like VerifierBuilder. It sounds worse, but does make more sense conceptually imo, since what you actually build with it are verifiers, not policies, and you can also set things that are not part of the policy - the certificate store. Any thoughts on this, @alex, @reaperhulk?

DISCLAIMER: I sound pretty confident about some of these things here, but I'm not a core contributor here, so take what I say with a small grain of salt 😄 I just happened to work on this feature.

@deivse
Copy link
Contributor

deivse commented Feb 17, 2025

And @loewexy, I think this would indeed benefit from a guide-style documentation entry, so if you will be able to take some of the stuff I laid out here and convert it to that format, that would be a great contribution!

Copy link

This issue has been waiting for a reporter response for 3 days. It will be auto-closed if no activity occurs in the next 5 days.

@github-actions github-actions bot added the Stale label Feb 21, 2025
@loewexy
Copy link
Author

loewexy commented Feb 23, 2025

Thanks for your answers. This will help me hopefully. However I will only work on this once the feature is released.

@github-actions github-actions bot removed the Stale label Feb 24, 2025
Copy link

This issue has been waiting for a reporter response for 3 days. It will be auto-closed if no activity occurs in the next 5 days.

@github-actions github-actions bot added the Stale label Feb 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Stale waiting-on-reporter Issue is waiting on a reply from the reporter. It will be automatically cloesd if there is no reply.
Development

No branches or pull requests

4 participants