Add x509.CustomExtensionType for user-defined extension types - #15599
Open
alex wants to merge 5 commits into
Open
Add x509.CustomExtensionType for user-defined extension types#15599alex wants to merge 5 commits into
alex wants to merge 5 commits into
Conversation
Custom extensions previously had to be handled by looking up the
UnrecognizedExtension by OID and manually running its value through
asn1.decode_der. CustomExtensionType lets users define an extension
class parameterized with the ASN.1 type of its value:
class PolicyMappings(x509.CustomExtensionType[list[PolicyMapping]]):
oid = ExtensionOID.POLICY_MAPPINGS
ext = cert.extensions.get_extension_for_class(PolicyMappings)
ext.value.value # list[PolicyMapping]
Extensions.get_extension_for_class parses the matching extension's DER
into the custom class, and instances can be passed to the certificate,
CRL, CSR, and OCSP builders' add_extension, which serialize them via the
declarative ASN.1 encoder.
To support values whose type can't be inferred from the value alone
(e.g. a top-level list[T]), the Rust declarative_asn1 module gains an
encode_der_with_type function that takes an explicit annotated type.
Refs #15500
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xp766iEvYJexKJZRx3Rm4v
The explicit-type encoder was orthogonal to custom extension support. CustomExtensionType.public_bytes() now uses asn1.encode_der directly, so values are encoded the same way as any other declarative ASN.1 value. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xp766iEvYJexKJZRx3Rm4v
- Simplify the changelog entry and drop the versionchanged note and documented TypeError from the docs. - Only parse UnrecognizedExtension values in get_extension_for_class, directly from their raw DER bytes, in a single pass over the extensions. - Use a simple Point sequence in the docs and tests instead of policy mappings. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xp766iEvYJexKJZRx3Rm4v
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xp766iEvYJexKJZRx3Rm4v
This replaces the loop over __orig_bases__ with a direct read of the single base, which is simpler and removes a branch that was never taken in tests. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xp766iEvYJexKJZRx3Rm4v
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #15500.
Adds
x509.CustomExtensionType, a base class for defining X.509 extension types thatcryptographydoes not natively support, usingcryptography.hazmat.asn1types for their values:Extensions.get_extension_for_classacceptsCustomExtensionTypesubclasses. When the matching extension is present as anUnrecognizedExtension, its DER value is decoded into the custom class and returned as a newExtension. The value is typed end to end: mypy seesext.value.valueasPoint.oid; both are validated at class-definition time.encode_extensionspath callspublic_bytes()for them, which encodes withasn1.encode_der.Of the two shapes discussed on the issue, the alias form
CustomExtensionType[T, ExtensionOID.X]is not feasible: type checkers reject a value as a type argument, and the runtime object is atyping._GenericAliasrather than a class. The subclass form is implemented here.🤖 Generated with Claude Code
https://claude.ai/code/session_01Xp766iEvYJexKJZRx3Rm4v
Generated by Claude Code