@pairling/runtime-darwin-arm64 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/pairling-connectd +0 -0
- package/manifest.json +4 -4
- package/package.json +1 -1
- package/python/bin/python3 +0 -0
- package/python/bin/python3.12 +0 -0
- package/python/lib/libpython3.12.dylib +0 -0
- package/python/lib/python3.12/__pycache__/__future__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/_compression.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/_weakrefset.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/base64.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/bisect.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/bz2.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/calendar.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/contextlib.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/copyreg.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/datetime.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/enum.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/fnmatch.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/functools.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/hashlib.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/hmac.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/ipaddress.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/keyword.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/locale.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/lzma.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/operator.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/plistlib.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/pty.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/quopri.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/random.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/reprlib.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/selectors.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/shutil.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/signal.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/socket.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/ssl.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/string.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/struct.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/subprocess.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/tempfile.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/threading.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/tty.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/types.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/typing.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/warnings.cpython-312.pyc +0 -0
- package/python/lib/python3.12/__pycache__/weakref.cpython-312.pyc +0 -0
- package/python/lib/python3.12/collections/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/collections/__pycache__/abc.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/_encoded_words.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/_parseaddr.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/_policybase.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/base64mime.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/charset.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/encoders.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/errors.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/feedparser.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/header.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/iterators.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/message.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/parser.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/quoprimime.cpython-312.pyc +0 -0
- package/python/lib/python3.12/email/__pycache__/utils.cpython-312.pyc +0 -0
- package/python/lib/python3.12/encodings/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/encodings/__pycache__/aliases.cpython-312.pyc +0 -0
- package/python/lib/python3.12/encodings/__pycache__/utf_8.cpython-312.pyc +0 -0
- package/python/lib/python3.12/http/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/http/__pycache__/client.cpython-312.pyc +0 -0
- package/python/lib/python3.12/json/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/json/__pycache__/decoder.cpython-312.pyc +0 -0
- package/python/lib/python3.12/json/__pycache__/encoder.cpython-312.pyc +0 -0
- package/python/lib/python3.12/json/__pycache__/scanner.cpython-312.pyc +0 -0
- package/python/lib/python3.12/lib-dynload/_crypt.cpython-312-darwin.so +0 -0
- package/python/lib/python3.12/lib-dynload/_dbm.cpython-312-darwin.so +0 -0
- package/python/lib/python3.12/re/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/re/__pycache__/_casefix.cpython-312.pyc +0 -0
- package/python/lib/python3.12/re/__pycache__/_compiler.cpython-312.pyc +0 -0
- package/python/lib/python3.12/re/__pycache__/_constants.cpython-312.pyc +0 -0
- package/python/lib/python3.12/re/__pycache__/_parser.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/_cffi_backend.cpython-312-darwin.so +0 -0
- package/python/lib/python3.12/site-packages/cffi/__init__.py +14 -0
- package/python/lib/python3.12/site-packages/cffi/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/cffi/__pycache__/api.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/cffi/__pycache__/error.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/cffi/__pycache__/lock.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/cffi/__pycache__/model.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/cffi/_cffi_errors.h +149 -0
- package/python/lib/python3.12/site-packages/cffi/_cffi_include.h +389 -0
- package/python/lib/python3.12/site-packages/cffi/_embedding.h +550 -0
- package/python/lib/python3.12/site-packages/cffi/_imp_emulation.py +83 -0
- package/python/lib/python3.12/site-packages/cffi/_shimmed_dist_utils.py +45 -0
- package/python/lib/python3.12/site-packages/cffi/api.py +967 -0
- package/python/lib/python3.12/site-packages/cffi/backend_ctypes.py +1121 -0
- package/python/lib/python3.12/site-packages/cffi/cffi_opcode.py +187 -0
- package/python/lib/python3.12/site-packages/cffi/commontypes.py +82 -0
- package/python/lib/python3.12/site-packages/cffi/cparser.py +1015 -0
- package/python/lib/python3.12/site-packages/cffi/error.py +31 -0
- package/python/lib/python3.12/site-packages/cffi/ffiplatform.py +113 -0
- package/python/lib/python3.12/site-packages/cffi/lock.py +30 -0
- package/python/lib/python3.12/site-packages/cffi/model.py +618 -0
- package/python/lib/python3.12/site-packages/cffi/parse_c_type.h +181 -0
- package/python/lib/python3.12/site-packages/cffi/pkgconfig.py +121 -0
- package/python/lib/python3.12/site-packages/cffi/recompiler.py +1598 -0
- package/python/lib/python3.12/site-packages/cffi/setuptools_ext.py +229 -0
- package/python/lib/python3.12/site-packages/cffi/vengine_cpy.py +1087 -0
- package/python/lib/python3.12/site-packages/cffi/vengine_gen.py +679 -0
- package/python/lib/python3.12/site-packages/cffi/verifier.py +306 -0
- package/python/lib/python3.12/site-packages/cffi-2.0.0.dist-info/INSTALLER +1 -0
- package/python/lib/python3.12/site-packages/cffi-2.0.0.dist-info/METADATA +68 -0
- package/python/lib/python3.12/site-packages/cffi-2.0.0.dist-info/RECORD +31 -0
- package/python/lib/python3.12/site-packages/cffi-2.0.0.dist-info/WHEEL +6 -0
- package/python/lib/python3.12/site-packages/cffi-2.0.0.dist-info/entry_points.txt +2 -0
- package/python/lib/python3.12/site-packages/cffi-2.0.0.dist-info/licenses/AUTHORS +8 -0
- package/python/lib/python3.12/site-packages/cffi-2.0.0.dist-info/licenses/LICENSE +23 -0
- package/python/lib/python3.12/site-packages/cffi-2.0.0.dist-info/top_level.txt +2 -0
- package/python/lib/python3.12/site-packages/cryptography/__about__.py +17 -0
- package/python/lib/python3.12/site-packages/cryptography/__init__.py +26 -0
- package/python/lib/python3.12/site-packages/cryptography/__pycache__/__about__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/cryptography/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/cryptography/__pycache__/utils.cpython-312.pyc +0 -0
- package/python/lib/python3.12/site-packages/cryptography/exceptions.py +52 -0
- package/python/lib/python3.12/site-packages/cryptography/fernet.py +224 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/__init__.py +13 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/_oid.py +348 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/backends/__init__.py +13 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/backends/openssl/__init__.py +9 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/backends/openssl/backend.py +308 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/__init__.py +3 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/__init__.pyi +37 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi +8 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi +7 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi +17 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi +117 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi +75 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi +107 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi +38 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi +18 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi +51 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi +41 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi +52 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi +13 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi +13 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi +28 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi +22 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi +49 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi +34 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi +15 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi +55 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi +13 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi +13 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/pkcs12.pyi +52 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi +50 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/test_support.pyi +23 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi +313 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/_rust.abi3.so +0 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/openssl/__init__.py +3 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py +191 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/bindings/openssl/binding.py +122 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/decrepit/__init__.py +5 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/decrepit/ciphers/__init__.py +5 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/decrepit/ciphers/algorithms.py +112 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/__init__.py +3 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/_asymmetric.py +19 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py +60 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/_serialization.py +168 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py +3 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py +147 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py +167 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py +447 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py +129 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py +131 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py +113 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py +277 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/types.py +111 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py +24 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py +122 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py +125 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py +27 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/ciphers/aead.py +23 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py +183 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/ciphers/base.py +146 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/ciphers/modes.py +268 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/cmac.py +10 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/constant_time.py +14 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/hashes.py +246 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/hmac.py +13 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/kdf/__init__.py +23 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/kdf/argon2.py +13 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py +125 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py +101 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py +305 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py +62 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py +19 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py +61 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/keywrap.py +177 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/padding.py +69 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/poly1305.py +11 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/serialization/__init__.py +65 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/serialization/base.py +14 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py +176 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py +411 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/serialization/ssh.py +1619 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py +9 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py +101 -0
- package/python/lib/python3.12/site-packages/cryptography/hazmat/primitives/twofactor/totp.py +56 -0
- package/python/lib/python3.12/site-packages/cryptography/py.typed +0 -0
- package/python/lib/python3.12/site-packages/cryptography/utils.py +139 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/__init__.py +270 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/base.py +848 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/certificate_transparency.py +35 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/extensions.py +2528 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/general_name.py +281 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/name.py +477 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/ocsp.py +379 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/oid.py +37 -0
- package/python/lib/python3.12/site-packages/cryptography/x509/verification.py +34 -0
- package/python/lib/python3.12/site-packages/cryptography-45.0.7.dist-info/INSTALLER +1 -0
- package/python/lib/python3.12/site-packages/cryptography-45.0.7.dist-info/METADATA +139 -0
- package/python/lib/python3.12/site-packages/cryptography-45.0.7.dist-info/RECORD +106 -0
- package/python/lib/python3.12/site-packages/cryptography-45.0.7.dist-info/REQUESTED +0 -0
- package/python/lib/python3.12/site-packages/cryptography-45.0.7.dist-info/WHEEL +4 -0
- package/python/lib/python3.12/site-packages/cryptography-45.0.7.dist-info/licenses/LICENSE +3 -0
- package/python/lib/python3.12/site-packages/cryptography-45.0.7.dist-info/licenses/LICENSE.APACHE +202 -0
- package/python/lib/python3.12/site-packages/cryptography-45.0.7.dist-info/licenses/LICENSE.BSD +27 -0
- package/python/lib/python3.12/site-packages/pycparser/__init__.py +99 -0
- package/python/lib/python3.12/site-packages/pycparser/_ast_gen.py +355 -0
- package/python/lib/python3.12/site-packages/pycparser/_c_ast.cfg +195 -0
- package/python/lib/python3.12/site-packages/pycparser/ast_transforms.py +174 -0
- package/python/lib/python3.12/site-packages/pycparser/c_ast.py +1341 -0
- package/python/lib/python3.12/site-packages/pycparser/c_generator.py +573 -0
- package/python/lib/python3.12/site-packages/pycparser/c_lexer.py +706 -0
- package/python/lib/python3.12/site-packages/pycparser/c_parser.py +2376 -0
- package/python/lib/python3.12/site-packages/pycparser-3.0.dist-info/INSTALLER +1 -0
- package/python/lib/python3.12/site-packages/pycparser-3.0.dist-info/METADATA +244 -0
- package/python/lib/python3.12/site-packages/pycparser-3.0.dist-info/RECORD +14 -0
- package/python/lib/python3.12/site-packages/pycparser-3.0.dist-info/WHEEL +5 -0
- package/python/lib/python3.12/site-packages/pycparser-3.0.dist-info/licenses/LICENSE +27 -0
- package/python/lib/python3.12/site-packages/pycparser-3.0.dist-info/top_level.txt +1 -0
- package/python/lib/python3.12/sqlite3/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/sqlite3/__pycache__/dbapi2.cpython-312.pyc +0 -0
- package/python/lib/python3.12/urllib/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/urllib/__pycache__/error.cpython-312.pyc +0 -0
- package/python/lib/python3.12/urllib/__pycache__/parse.cpython-312.pyc +0 -0
- package/python/lib/python3.12/urllib/__pycache__/request.cpython-312.pyc +0 -0
- package/python/lib/python3.12/urllib/__pycache__/response.cpython-312.pyc +0 -0
- package/python/lib/python3.12/xml/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/xml/parsers/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/lib/python3.12/xml/parsers/__pycache__/expat.cpython-312.pyc +0 -0
|
@@ -0,0 +1,2528 @@
|
|
|
1
|
+
# This file is dual licensed under the terms of the Apache License, Version
|
|
2
|
+
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
|
3
|
+
# for complete details.
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import abc
|
|
8
|
+
import datetime
|
|
9
|
+
import hashlib
|
|
10
|
+
import ipaddress
|
|
11
|
+
import typing
|
|
12
|
+
from collections.abc import Iterable, Iterator
|
|
13
|
+
|
|
14
|
+
from cryptography import utils
|
|
15
|
+
from cryptography.hazmat.bindings._rust import asn1
|
|
16
|
+
from cryptography.hazmat.bindings._rust import x509 as rust_x509
|
|
17
|
+
from cryptography.hazmat.primitives import constant_time, serialization
|
|
18
|
+
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
|
|
19
|
+
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
|
|
20
|
+
from cryptography.hazmat.primitives.asymmetric.types import (
|
|
21
|
+
CertificateIssuerPublicKeyTypes,
|
|
22
|
+
CertificatePublicKeyTypes,
|
|
23
|
+
)
|
|
24
|
+
from cryptography.x509.certificate_transparency import (
|
|
25
|
+
SignedCertificateTimestamp,
|
|
26
|
+
)
|
|
27
|
+
from cryptography.x509.general_name import (
|
|
28
|
+
DirectoryName,
|
|
29
|
+
DNSName,
|
|
30
|
+
GeneralName,
|
|
31
|
+
IPAddress,
|
|
32
|
+
OtherName,
|
|
33
|
+
RegisteredID,
|
|
34
|
+
RFC822Name,
|
|
35
|
+
UniformResourceIdentifier,
|
|
36
|
+
_IPAddressTypes,
|
|
37
|
+
)
|
|
38
|
+
from cryptography.x509.name import Name, RelativeDistinguishedName
|
|
39
|
+
from cryptography.x509.oid import (
|
|
40
|
+
CRLEntryExtensionOID,
|
|
41
|
+
ExtensionOID,
|
|
42
|
+
ObjectIdentifier,
|
|
43
|
+
OCSPExtensionOID,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
ExtensionTypeVar = typing.TypeVar(
|
|
47
|
+
"ExtensionTypeVar", bound="ExtensionType", covariant=True
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _key_identifier_from_public_key(
|
|
52
|
+
public_key: CertificatePublicKeyTypes,
|
|
53
|
+
) -> bytes:
|
|
54
|
+
if isinstance(public_key, RSAPublicKey):
|
|
55
|
+
data = public_key.public_bytes(
|
|
56
|
+
serialization.Encoding.DER,
|
|
57
|
+
serialization.PublicFormat.PKCS1,
|
|
58
|
+
)
|
|
59
|
+
elif isinstance(public_key, EllipticCurvePublicKey):
|
|
60
|
+
data = public_key.public_bytes(
|
|
61
|
+
serialization.Encoding.X962,
|
|
62
|
+
serialization.PublicFormat.UncompressedPoint,
|
|
63
|
+
)
|
|
64
|
+
else:
|
|
65
|
+
# This is a very slow way to do this.
|
|
66
|
+
serialized = public_key.public_bytes(
|
|
67
|
+
serialization.Encoding.DER,
|
|
68
|
+
serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
69
|
+
)
|
|
70
|
+
data = asn1.parse_spki_for_data(serialized)
|
|
71
|
+
|
|
72
|
+
return hashlib.sha1(data).digest()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _make_sequence_methods(field_name: str):
|
|
76
|
+
def len_method(self) -> int:
|
|
77
|
+
return len(getattr(self, field_name))
|
|
78
|
+
|
|
79
|
+
def iter_method(self):
|
|
80
|
+
return iter(getattr(self, field_name))
|
|
81
|
+
|
|
82
|
+
def getitem_method(self, idx):
|
|
83
|
+
return getattr(self, field_name)[idx]
|
|
84
|
+
|
|
85
|
+
return len_method, iter_method, getitem_method
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class DuplicateExtension(Exception):
|
|
89
|
+
def __init__(self, msg: str, oid: ObjectIdentifier) -> None:
|
|
90
|
+
super().__init__(msg)
|
|
91
|
+
self.oid = oid
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class ExtensionNotFound(Exception):
|
|
95
|
+
def __init__(self, msg: str, oid: ObjectIdentifier) -> None:
|
|
96
|
+
super().__init__(msg)
|
|
97
|
+
self.oid = oid
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class ExtensionType(metaclass=abc.ABCMeta):
|
|
101
|
+
oid: typing.ClassVar[ObjectIdentifier]
|
|
102
|
+
|
|
103
|
+
def public_bytes(self) -> bytes:
|
|
104
|
+
"""
|
|
105
|
+
Serializes the extension type to DER.
|
|
106
|
+
"""
|
|
107
|
+
raise NotImplementedError(
|
|
108
|
+
f"public_bytes is not implemented for extension type {self!r}"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class Extensions:
|
|
113
|
+
def __init__(self, extensions: Iterable[Extension[ExtensionType]]) -> None:
|
|
114
|
+
self._extensions = list(extensions)
|
|
115
|
+
|
|
116
|
+
def get_extension_for_oid(
|
|
117
|
+
self, oid: ObjectIdentifier
|
|
118
|
+
) -> Extension[ExtensionType]:
|
|
119
|
+
for ext in self:
|
|
120
|
+
if ext.oid == oid:
|
|
121
|
+
return ext
|
|
122
|
+
|
|
123
|
+
raise ExtensionNotFound(f"No {oid} extension was found", oid)
|
|
124
|
+
|
|
125
|
+
def get_extension_for_class(
|
|
126
|
+
self, extclass: type[ExtensionTypeVar]
|
|
127
|
+
) -> Extension[ExtensionTypeVar]:
|
|
128
|
+
if extclass is UnrecognizedExtension:
|
|
129
|
+
raise TypeError(
|
|
130
|
+
"UnrecognizedExtension can't be used with "
|
|
131
|
+
"get_extension_for_class because more than one instance of the"
|
|
132
|
+
" class may be present."
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
for ext in self:
|
|
136
|
+
if isinstance(ext.value, extclass):
|
|
137
|
+
return ext
|
|
138
|
+
|
|
139
|
+
raise ExtensionNotFound(
|
|
140
|
+
f"No {extclass} extension was found", extclass.oid
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_extensions")
|
|
144
|
+
|
|
145
|
+
def __repr__(self) -> str:
|
|
146
|
+
return f"<Extensions({self._extensions})>"
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class CRLNumber(ExtensionType):
|
|
150
|
+
oid = ExtensionOID.CRL_NUMBER
|
|
151
|
+
|
|
152
|
+
def __init__(self, crl_number: int) -> None:
|
|
153
|
+
if not isinstance(crl_number, int):
|
|
154
|
+
raise TypeError("crl_number must be an integer")
|
|
155
|
+
|
|
156
|
+
self._crl_number = crl_number
|
|
157
|
+
|
|
158
|
+
def __eq__(self, other: object) -> bool:
|
|
159
|
+
if not isinstance(other, CRLNumber):
|
|
160
|
+
return NotImplemented
|
|
161
|
+
|
|
162
|
+
return self.crl_number == other.crl_number
|
|
163
|
+
|
|
164
|
+
def __hash__(self) -> int:
|
|
165
|
+
return hash(self.crl_number)
|
|
166
|
+
|
|
167
|
+
def __repr__(self) -> str:
|
|
168
|
+
return f"<CRLNumber({self.crl_number})>"
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def crl_number(self) -> int:
|
|
172
|
+
return self._crl_number
|
|
173
|
+
|
|
174
|
+
def public_bytes(self) -> bytes:
|
|
175
|
+
return rust_x509.encode_extension_value(self)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class AuthorityKeyIdentifier(ExtensionType):
|
|
179
|
+
oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER
|
|
180
|
+
|
|
181
|
+
def __init__(
|
|
182
|
+
self,
|
|
183
|
+
key_identifier: bytes | None,
|
|
184
|
+
authority_cert_issuer: Iterable[GeneralName] | None,
|
|
185
|
+
authority_cert_serial_number: int | None,
|
|
186
|
+
) -> None:
|
|
187
|
+
if (authority_cert_issuer is None) != (
|
|
188
|
+
authority_cert_serial_number is None
|
|
189
|
+
):
|
|
190
|
+
raise ValueError(
|
|
191
|
+
"authority_cert_issuer and authority_cert_serial_number "
|
|
192
|
+
"must both be present or both None"
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
if authority_cert_issuer is not None:
|
|
196
|
+
authority_cert_issuer = list(authority_cert_issuer)
|
|
197
|
+
if not all(
|
|
198
|
+
isinstance(x, GeneralName) for x in authority_cert_issuer
|
|
199
|
+
):
|
|
200
|
+
raise TypeError(
|
|
201
|
+
"authority_cert_issuer must be a list of GeneralName "
|
|
202
|
+
"objects"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if authority_cert_serial_number is not None and not isinstance(
|
|
206
|
+
authority_cert_serial_number, int
|
|
207
|
+
):
|
|
208
|
+
raise TypeError("authority_cert_serial_number must be an integer")
|
|
209
|
+
|
|
210
|
+
self._key_identifier = key_identifier
|
|
211
|
+
self._authority_cert_issuer = authority_cert_issuer
|
|
212
|
+
self._authority_cert_serial_number = authority_cert_serial_number
|
|
213
|
+
|
|
214
|
+
# This takes a subset of CertificatePublicKeyTypes because an issuer
|
|
215
|
+
# cannot have an X25519/X448 key. This introduces some unfortunate
|
|
216
|
+
# asymmetry that requires typing users to explicitly
|
|
217
|
+
# narrow their type, but we should make this accurate and not just
|
|
218
|
+
# convenient.
|
|
219
|
+
@classmethod
|
|
220
|
+
def from_issuer_public_key(
|
|
221
|
+
cls, public_key: CertificateIssuerPublicKeyTypes
|
|
222
|
+
) -> AuthorityKeyIdentifier:
|
|
223
|
+
digest = _key_identifier_from_public_key(public_key)
|
|
224
|
+
return cls(
|
|
225
|
+
key_identifier=digest,
|
|
226
|
+
authority_cert_issuer=None,
|
|
227
|
+
authority_cert_serial_number=None,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
@classmethod
|
|
231
|
+
def from_issuer_subject_key_identifier(
|
|
232
|
+
cls, ski: SubjectKeyIdentifier
|
|
233
|
+
) -> AuthorityKeyIdentifier:
|
|
234
|
+
return cls(
|
|
235
|
+
key_identifier=ski.digest,
|
|
236
|
+
authority_cert_issuer=None,
|
|
237
|
+
authority_cert_serial_number=None,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def __repr__(self) -> str:
|
|
241
|
+
return (
|
|
242
|
+
f"<AuthorityKeyIdentifier(key_identifier={self.key_identifier!r}, "
|
|
243
|
+
f"authority_cert_issuer={self.authority_cert_issuer}, "
|
|
244
|
+
f"authority_cert_serial_number={self.authority_cert_serial_number}"
|
|
245
|
+
")>"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
def __eq__(self, other: object) -> bool:
|
|
249
|
+
if not isinstance(other, AuthorityKeyIdentifier):
|
|
250
|
+
return NotImplemented
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
self.key_identifier == other.key_identifier
|
|
254
|
+
and self.authority_cert_issuer == other.authority_cert_issuer
|
|
255
|
+
and self.authority_cert_serial_number
|
|
256
|
+
== other.authority_cert_serial_number
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
def __hash__(self) -> int:
|
|
260
|
+
if self.authority_cert_issuer is None:
|
|
261
|
+
aci = None
|
|
262
|
+
else:
|
|
263
|
+
aci = tuple(self.authority_cert_issuer)
|
|
264
|
+
return hash(
|
|
265
|
+
(self.key_identifier, aci, self.authority_cert_serial_number)
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
@property
|
|
269
|
+
def key_identifier(self) -> bytes | None:
|
|
270
|
+
return self._key_identifier
|
|
271
|
+
|
|
272
|
+
@property
|
|
273
|
+
def authority_cert_issuer(
|
|
274
|
+
self,
|
|
275
|
+
) -> list[GeneralName] | None:
|
|
276
|
+
return self._authority_cert_issuer
|
|
277
|
+
|
|
278
|
+
@property
|
|
279
|
+
def authority_cert_serial_number(self) -> int | None:
|
|
280
|
+
return self._authority_cert_serial_number
|
|
281
|
+
|
|
282
|
+
def public_bytes(self) -> bytes:
|
|
283
|
+
return rust_x509.encode_extension_value(self)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class SubjectKeyIdentifier(ExtensionType):
|
|
287
|
+
oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER
|
|
288
|
+
|
|
289
|
+
def __init__(self, digest: bytes) -> None:
|
|
290
|
+
self._digest = digest
|
|
291
|
+
|
|
292
|
+
@classmethod
|
|
293
|
+
def from_public_key(
|
|
294
|
+
cls, public_key: CertificatePublicKeyTypes
|
|
295
|
+
) -> SubjectKeyIdentifier:
|
|
296
|
+
return cls(_key_identifier_from_public_key(public_key))
|
|
297
|
+
|
|
298
|
+
@property
|
|
299
|
+
def digest(self) -> bytes:
|
|
300
|
+
return self._digest
|
|
301
|
+
|
|
302
|
+
@property
|
|
303
|
+
def key_identifier(self) -> bytes:
|
|
304
|
+
return self._digest
|
|
305
|
+
|
|
306
|
+
def __repr__(self) -> str:
|
|
307
|
+
return f"<SubjectKeyIdentifier(digest={self.digest!r})>"
|
|
308
|
+
|
|
309
|
+
def __eq__(self, other: object) -> bool:
|
|
310
|
+
if not isinstance(other, SubjectKeyIdentifier):
|
|
311
|
+
return NotImplemented
|
|
312
|
+
|
|
313
|
+
return constant_time.bytes_eq(self.digest, other.digest)
|
|
314
|
+
|
|
315
|
+
def __hash__(self) -> int:
|
|
316
|
+
return hash(self.digest)
|
|
317
|
+
|
|
318
|
+
def public_bytes(self) -> bytes:
|
|
319
|
+
return rust_x509.encode_extension_value(self)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class AuthorityInformationAccess(ExtensionType):
|
|
323
|
+
oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS
|
|
324
|
+
|
|
325
|
+
def __init__(self, descriptions: Iterable[AccessDescription]) -> None:
|
|
326
|
+
descriptions = list(descriptions)
|
|
327
|
+
if not all(isinstance(x, AccessDescription) for x in descriptions):
|
|
328
|
+
raise TypeError(
|
|
329
|
+
"Every item in the descriptions list must be an "
|
|
330
|
+
"AccessDescription"
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
self._descriptions = descriptions
|
|
334
|
+
|
|
335
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
|
|
336
|
+
|
|
337
|
+
def __repr__(self) -> str:
|
|
338
|
+
return f"<AuthorityInformationAccess({self._descriptions})>"
|
|
339
|
+
|
|
340
|
+
def __eq__(self, other: object) -> bool:
|
|
341
|
+
if not isinstance(other, AuthorityInformationAccess):
|
|
342
|
+
return NotImplemented
|
|
343
|
+
|
|
344
|
+
return self._descriptions == other._descriptions
|
|
345
|
+
|
|
346
|
+
def __hash__(self) -> int:
|
|
347
|
+
return hash(tuple(self._descriptions))
|
|
348
|
+
|
|
349
|
+
def public_bytes(self) -> bytes:
|
|
350
|
+
return rust_x509.encode_extension_value(self)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
class SubjectInformationAccess(ExtensionType):
|
|
354
|
+
oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS
|
|
355
|
+
|
|
356
|
+
def __init__(self, descriptions: Iterable[AccessDescription]) -> None:
|
|
357
|
+
descriptions = list(descriptions)
|
|
358
|
+
if not all(isinstance(x, AccessDescription) for x in descriptions):
|
|
359
|
+
raise TypeError(
|
|
360
|
+
"Every item in the descriptions list must be an "
|
|
361
|
+
"AccessDescription"
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
self._descriptions = descriptions
|
|
365
|
+
|
|
366
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
|
|
367
|
+
|
|
368
|
+
def __repr__(self) -> str:
|
|
369
|
+
return f"<SubjectInformationAccess({self._descriptions})>"
|
|
370
|
+
|
|
371
|
+
def __eq__(self, other: object) -> bool:
|
|
372
|
+
if not isinstance(other, SubjectInformationAccess):
|
|
373
|
+
return NotImplemented
|
|
374
|
+
|
|
375
|
+
return self._descriptions == other._descriptions
|
|
376
|
+
|
|
377
|
+
def __hash__(self) -> int:
|
|
378
|
+
return hash(tuple(self._descriptions))
|
|
379
|
+
|
|
380
|
+
def public_bytes(self) -> bytes:
|
|
381
|
+
return rust_x509.encode_extension_value(self)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
class AccessDescription:
|
|
385
|
+
def __init__(
|
|
386
|
+
self, access_method: ObjectIdentifier, access_location: GeneralName
|
|
387
|
+
) -> None:
|
|
388
|
+
if not isinstance(access_method, ObjectIdentifier):
|
|
389
|
+
raise TypeError("access_method must be an ObjectIdentifier")
|
|
390
|
+
|
|
391
|
+
if not isinstance(access_location, GeneralName):
|
|
392
|
+
raise TypeError("access_location must be a GeneralName")
|
|
393
|
+
|
|
394
|
+
self._access_method = access_method
|
|
395
|
+
self._access_location = access_location
|
|
396
|
+
|
|
397
|
+
def __repr__(self) -> str:
|
|
398
|
+
return (
|
|
399
|
+
f"<AccessDescription(access_method={self.access_method}, "
|
|
400
|
+
f"access_location={self.access_location})>"
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
def __eq__(self, other: object) -> bool:
|
|
404
|
+
if not isinstance(other, AccessDescription):
|
|
405
|
+
return NotImplemented
|
|
406
|
+
|
|
407
|
+
return (
|
|
408
|
+
self.access_method == other.access_method
|
|
409
|
+
and self.access_location == other.access_location
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
def __hash__(self) -> int:
|
|
413
|
+
return hash((self.access_method, self.access_location))
|
|
414
|
+
|
|
415
|
+
@property
|
|
416
|
+
def access_method(self) -> ObjectIdentifier:
|
|
417
|
+
return self._access_method
|
|
418
|
+
|
|
419
|
+
@property
|
|
420
|
+
def access_location(self) -> GeneralName:
|
|
421
|
+
return self._access_location
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
class BasicConstraints(ExtensionType):
|
|
425
|
+
oid = ExtensionOID.BASIC_CONSTRAINTS
|
|
426
|
+
|
|
427
|
+
def __init__(self, ca: bool, path_length: int | None) -> None:
|
|
428
|
+
if not isinstance(ca, bool):
|
|
429
|
+
raise TypeError("ca must be a boolean value")
|
|
430
|
+
|
|
431
|
+
if path_length is not None and not ca:
|
|
432
|
+
raise ValueError("path_length must be None when ca is False")
|
|
433
|
+
|
|
434
|
+
if path_length is not None and (
|
|
435
|
+
not isinstance(path_length, int) or path_length < 0
|
|
436
|
+
):
|
|
437
|
+
raise TypeError(
|
|
438
|
+
"path_length must be a non-negative integer or None"
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
self._ca = ca
|
|
442
|
+
self._path_length = path_length
|
|
443
|
+
|
|
444
|
+
@property
|
|
445
|
+
def ca(self) -> bool:
|
|
446
|
+
return self._ca
|
|
447
|
+
|
|
448
|
+
@property
|
|
449
|
+
def path_length(self) -> int | None:
|
|
450
|
+
return self._path_length
|
|
451
|
+
|
|
452
|
+
def __repr__(self) -> str:
|
|
453
|
+
return (
|
|
454
|
+
f"<BasicConstraints(ca={self.ca}, path_length={self.path_length})>"
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
def __eq__(self, other: object) -> bool:
|
|
458
|
+
if not isinstance(other, BasicConstraints):
|
|
459
|
+
return NotImplemented
|
|
460
|
+
|
|
461
|
+
return self.ca == other.ca and self.path_length == other.path_length
|
|
462
|
+
|
|
463
|
+
def __hash__(self) -> int:
|
|
464
|
+
return hash((self.ca, self.path_length))
|
|
465
|
+
|
|
466
|
+
def public_bytes(self) -> bytes:
|
|
467
|
+
return rust_x509.encode_extension_value(self)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
class DeltaCRLIndicator(ExtensionType):
|
|
471
|
+
oid = ExtensionOID.DELTA_CRL_INDICATOR
|
|
472
|
+
|
|
473
|
+
def __init__(self, crl_number: int) -> None:
|
|
474
|
+
if not isinstance(crl_number, int):
|
|
475
|
+
raise TypeError("crl_number must be an integer")
|
|
476
|
+
|
|
477
|
+
self._crl_number = crl_number
|
|
478
|
+
|
|
479
|
+
@property
|
|
480
|
+
def crl_number(self) -> int:
|
|
481
|
+
return self._crl_number
|
|
482
|
+
|
|
483
|
+
def __eq__(self, other: object) -> bool:
|
|
484
|
+
if not isinstance(other, DeltaCRLIndicator):
|
|
485
|
+
return NotImplemented
|
|
486
|
+
|
|
487
|
+
return self.crl_number == other.crl_number
|
|
488
|
+
|
|
489
|
+
def __hash__(self) -> int:
|
|
490
|
+
return hash(self.crl_number)
|
|
491
|
+
|
|
492
|
+
def __repr__(self) -> str:
|
|
493
|
+
return f"<DeltaCRLIndicator(crl_number={self.crl_number})>"
|
|
494
|
+
|
|
495
|
+
def public_bytes(self) -> bytes:
|
|
496
|
+
return rust_x509.encode_extension_value(self)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
class CRLDistributionPoints(ExtensionType):
|
|
500
|
+
oid = ExtensionOID.CRL_DISTRIBUTION_POINTS
|
|
501
|
+
|
|
502
|
+
def __init__(
|
|
503
|
+
self, distribution_points: Iterable[DistributionPoint]
|
|
504
|
+
) -> None:
|
|
505
|
+
distribution_points = list(distribution_points)
|
|
506
|
+
if not all(
|
|
507
|
+
isinstance(x, DistributionPoint) for x in distribution_points
|
|
508
|
+
):
|
|
509
|
+
raise TypeError(
|
|
510
|
+
"distribution_points must be a list of DistributionPoint "
|
|
511
|
+
"objects"
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
self._distribution_points = distribution_points
|
|
515
|
+
|
|
516
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods(
|
|
517
|
+
"_distribution_points"
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
def __repr__(self) -> str:
|
|
521
|
+
return f"<CRLDistributionPoints({self._distribution_points})>"
|
|
522
|
+
|
|
523
|
+
def __eq__(self, other: object) -> bool:
|
|
524
|
+
if not isinstance(other, CRLDistributionPoints):
|
|
525
|
+
return NotImplemented
|
|
526
|
+
|
|
527
|
+
return self._distribution_points == other._distribution_points
|
|
528
|
+
|
|
529
|
+
def __hash__(self) -> int:
|
|
530
|
+
return hash(tuple(self._distribution_points))
|
|
531
|
+
|
|
532
|
+
def public_bytes(self) -> bytes:
|
|
533
|
+
return rust_x509.encode_extension_value(self)
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
class FreshestCRL(ExtensionType):
|
|
537
|
+
oid = ExtensionOID.FRESHEST_CRL
|
|
538
|
+
|
|
539
|
+
def __init__(
|
|
540
|
+
self, distribution_points: Iterable[DistributionPoint]
|
|
541
|
+
) -> None:
|
|
542
|
+
distribution_points = list(distribution_points)
|
|
543
|
+
if not all(
|
|
544
|
+
isinstance(x, DistributionPoint) for x in distribution_points
|
|
545
|
+
):
|
|
546
|
+
raise TypeError(
|
|
547
|
+
"distribution_points must be a list of DistributionPoint "
|
|
548
|
+
"objects"
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
self._distribution_points = distribution_points
|
|
552
|
+
|
|
553
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods(
|
|
554
|
+
"_distribution_points"
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
def __repr__(self) -> str:
|
|
558
|
+
return f"<FreshestCRL({self._distribution_points})>"
|
|
559
|
+
|
|
560
|
+
def __eq__(self, other: object) -> bool:
|
|
561
|
+
if not isinstance(other, FreshestCRL):
|
|
562
|
+
return NotImplemented
|
|
563
|
+
|
|
564
|
+
return self._distribution_points == other._distribution_points
|
|
565
|
+
|
|
566
|
+
def __hash__(self) -> int:
|
|
567
|
+
return hash(tuple(self._distribution_points))
|
|
568
|
+
|
|
569
|
+
def public_bytes(self) -> bytes:
|
|
570
|
+
return rust_x509.encode_extension_value(self)
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
class DistributionPoint:
|
|
574
|
+
def __init__(
|
|
575
|
+
self,
|
|
576
|
+
full_name: Iterable[GeneralName] | None,
|
|
577
|
+
relative_name: RelativeDistinguishedName | None,
|
|
578
|
+
reasons: frozenset[ReasonFlags] | None,
|
|
579
|
+
crl_issuer: Iterable[GeneralName] | None,
|
|
580
|
+
) -> None:
|
|
581
|
+
if full_name and relative_name:
|
|
582
|
+
raise ValueError(
|
|
583
|
+
"You cannot provide both full_name and relative_name, at "
|
|
584
|
+
"least one must be None."
|
|
585
|
+
)
|
|
586
|
+
if not full_name and not relative_name and not crl_issuer:
|
|
587
|
+
raise ValueError(
|
|
588
|
+
"Either full_name, relative_name or crl_issuer must be "
|
|
589
|
+
"provided."
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
if full_name is not None:
|
|
593
|
+
full_name = list(full_name)
|
|
594
|
+
if not all(isinstance(x, GeneralName) for x in full_name):
|
|
595
|
+
raise TypeError(
|
|
596
|
+
"full_name must be a list of GeneralName objects"
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
if relative_name:
|
|
600
|
+
if not isinstance(relative_name, RelativeDistinguishedName):
|
|
601
|
+
raise TypeError(
|
|
602
|
+
"relative_name must be a RelativeDistinguishedName"
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
if crl_issuer is not None:
|
|
606
|
+
crl_issuer = list(crl_issuer)
|
|
607
|
+
if not all(isinstance(x, GeneralName) for x in crl_issuer):
|
|
608
|
+
raise TypeError(
|
|
609
|
+
"crl_issuer must be None or a list of general names"
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
if reasons and (
|
|
613
|
+
not isinstance(reasons, frozenset)
|
|
614
|
+
or not all(isinstance(x, ReasonFlags) for x in reasons)
|
|
615
|
+
):
|
|
616
|
+
raise TypeError("reasons must be None or frozenset of ReasonFlags")
|
|
617
|
+
|
|
618
|
+
if reasons and (
|
|
619
|
+
ReasonFlags.unspecified in reasons
|
|
620
|
+
or ReasonFlags.remove_from_crl in reasons
|
|
621
|
+
):
|
|
622
|
+
raise ValueError(
|
|
623
|
+
"unspecified and remove_from_crl are not valid reasons in a "
|
|
624
|
+
"DistributionPoint"
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
self._full_name = full_name
|
|
628
|
+
self._relative_name = relative_name
|
|
629
|
+
self._reasons = reasons
|
|
630
|
+
self._crl_issuer = crl_issuer
|
|
631
|
+
|
|
632
|
+
def __repr__(self) -> str:
|
|
633
|
+
return (
|
|
634
|
+
"<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
|
|
635
|
+
"tive_name}, reasons={0.reasons}, "
|
|
636
|
+
"crl_issuer={0.crl_issuer})>".format(self)
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
def __eq__(self, other: object) -> bool:
|
|
640
|
+
if not isinstance(other, DistributionPoint):
|
|
641
|
+
return NotImplemented
|
|
642
|
+
|
|
643
|
+
return (
|
|
644
|
+
self.full_name == other.full_name
|
|
645
|
+
and self.relative_name == other.relative_name
|
|
646
|
+
and self.reasons == other.reasons
|
|
647
|
+
and self.crl_issuer == other.crl_issuer
|
|
648
|
+
)
|
|
649
|
+
|
|
650
|
+
def __hash__(self) -> int:
|
|
651
|
+
if self.full_name is not None:
|
|
652
|
+
fn: tuple[GeneralName, ...] | None = tuple(self.full_name)
|
|
653
|
+
else:
|
|
654
|
+
fn = None
|
|
655
|
+
|
|
656
|
+
if self.crl_issuer is not None:
|
|
657
|
+
crl_issuer: tuple[GeneralName, ...] | None = tuple(self.crl_issuer)
|
|
658
|
+
else:
|
|
659
|
+
crl_issuer = None
|
|
660
|
+
|
|
661
|
+
return hash((fn, self.relative_name, self.reasons, crl_issuer))
|
|
662
|
+
|
|
663
|
+
@property
|
|
664
|
+
def full_name(self) -> list[GeneralName] | None:
|
|
665
|
+
return self._full_name
|
|
666
|
+
|
|
667
|
+
@property
|
|
668
|
+
def relative_name(self) -> RelativeDistinguishedName | None:
|
|
669
|
+
return self._relative_name
|
|
670
|
+
|
|
671
|
+
@property
|
|
672
|
+
def reasons(self) -> frozenset[ReasonFlags] | None:
|
|
673
|
+
return self._reasons
|
|
674
|
+
|
|
675
|
+
@property
|
|
676
|
+
def crl_issuer(self) -> list[GeneralName] | None:
|
|
677
|
+
return self._crl_issuer
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
class ReasonFlags(utils.Enum):
|
|
681
|
+
unspecified = "unspecified"
|
|
682
|
+
key_compromise = "keyCompromise"
|
|
683
|
+
ca_compromise = "cACompromise"
|
|
684
|
+
affiliation_changed = "affiliationChanged"
|
|
685
|
+
superseded = "superseded"
|
|
686
|
+
cessation_of_operation = "cessationOfOperation"
|
|
687
|
+
certificate_hold = "certificateHold"
|
|
688
|
+
privilege_withdrawn = "privilegeWithdrawn"
|
|
689
|
+
aa_compromise = "aACompromise"
|
|
690
|
+
remove_from_crl = "removeFromCRL"
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
# These are distribution point bit string mappings. Not to be confused with
|
|
694
|
+
# CRLReason reason flags bit string mappings.
|
|
695
|
+
# ReasonFlags ::= BIT STRING {
|
|
696
|
+
# unused (0),
|
|
697
|
+
# keyCompromise (1),
|
|
698
|
+
# cACompromise (2),
|
|
699
|
+
# affiliationChanged (3),
|
|
700
|
+
# superseded (4),
|
|
701
|
+
# cessationOfOperation (5),
|
|
702
|
+
# certificateHold (6),
|
|
703
|
+
# privilegeWithdrawn (7),
|
|
704
|
+
# aACompromise (8) }
|
|
705
|
+
_REASON_BIT_MAPPING = {
|
|
706
|
+
1: ReasonFlags.key_compromise,
|
|
707
|
+
2: ReasonFlags.ca_compromise,
|
|
708
|
+
3: ReasonFlags.affiliation_changed,
|
|
709
|
+
4: ReasonFlags.superseded,
|
|
710
|
+
5: ReasonFlags.cessation_of_operation,
|
|
711
|
+
6: ReasonFlags.certificate_hold,
|
|
712
|
+
7: ReasonFlags.privilege_withdrawn,
|
|
713
|
+
8: ReasonFlags.aa_compromise,
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
_CRLREASONFLAGS = {
|
|
717
|
+
ReasonFlags.key_compromise: 1,
|
|
718
|
+
ReasonFlags.ca_compromise: 2,
|
|
719
|
+
ReasonFlags.affiliation_changed: 3,
|
|
720
|
+
ReasonFlags.superseded: 4,
|
|
721
|
+
ReasonFlags.cessation_of_operation: 5,
|
|
722
|
+
ReasonFlags.certificate_hold: 6,
|
|
723
|
+
ReasonFlags.privilege_withdrawn: 7,
|
|
724
|
+
ReasonFlags.aa_compromise: 8,
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
# CRLReason ::= ENUMERATED {
|
|
728
|
+
# unspecified (0),
|
|
729
|
+
# keyCompromise (1),
|
|
730
|
+
# cACompromise (2),
|
|
731
|
+
# affiliationChanged (3),
|
|
732
|
+
# superseded (4),
|
|
733
|
+
# cessationOfOperation (5),
|
|
734
|
+
# certificateHold (6),
|
|
735
|
+
# -- value 7 is not used
|
|
736
|
+
# removeFromCRL (8),
|
|
737
|
+
# privilegeWithdrawn (9),
|
|
738
|
+
# aACompromise (10) }
|
|
739
|
+
_CRL_ENTRY_REASON_ENUM_TO_CODE = {
|
|
740
|
+
ReasonFlags.unspecified: 0,
|
|
741
|
+
ReasonFlags.key_compromise: 1,
|
|
742
|
+
ReasonFlags.ca_compromise: 2,
|
|
743
|
+
ReasonFlags.affiliation_changed: 3,
|
|
744
|
+
ReasonFlags.superseded: 4,
|
|
745
|
+
ReasonFlags.cessation_of_operation: 5,
|
|
746
|
+
ReasonFlags.certificate_hold: 6,
|
|
747
|
+
ReasonFlags.remove_from_crl: 8,
|
|
748
|
+
ReasonFlags.privilege_withdrawn: 9,
|
|
749
|
+
ReasonFlags.aa_compromise: 10,
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
class PolicyConstraints(ExtensionType):
|
|
754
|
+
oid = ExtensionOID.POLICY_CONSTRAINTS
|
|
755
|
+
|
|
756
|
+
def __init__(
|
|
757
|
+
self,
|
|
758
|
+
require_explicit_policy: int | None,
|
|
759
|
+
inhibit_policy_mapping: int | None,
|
|
760
|
+
) -> None:
|
|
761
|
+
if require_explicit_policy is not None and not isinstance(
|
|
762
|
+
require_explicit_policy, int
|
|
763
|
+
):
|
|
764
|
+
raise TypeError(
|
|
765
|
+
"require_explicit_policy must be a non-negative integer or "
|
|
766
|
+
"None"
|
|
767
|
+
)
|
|
768
|
+
|
|
769
|
+
if inhibit_policy_mapping is not None and not isinstance(
|
|
770
|
+
inhibit_policy_mapping, int
|
|
771
|
+
):
|
|
772
|
+
raise TypeError(
|
|
773
|
+
"inhibit_policy_mapping must be a non-negative integer or None"
|
|
774
|
+
)
|
|
775
|
+
|
|
776
|
+
if inhibit_policy_mapping is None and require_explicit_policy is None:
|
|
777
|
+
raise ValueError(
|
|
778
|
+
"At least one of require_explicit_policy and "
|
|
779
|
+
"inhibit_policy_mapping must not be None"
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
self._require_explicit_policy = require_explicit_policy
|
|
783
|
+
self._inhibit_policy_mapping = inhibit_policy_mapping
|
|
784
|
+
|
|
785
|
+
def __repr__(self) -> str:
|
|
786
|
+
return (
|
|
787
|
+
"<PolicyConstraints(require_explicit_policy={0.require_explicit"
|
|
788
|
+
"_policy}, inhibit_policy_mapping={0.inhibit_policy_"
|
|
789
|
+
"mapping})>".format(self)
|
|
790
|
+
)
|
|
791
|
+
|
|
792
|
+
def __eq__(self, other: object) -> bool:
|
|
793
|
+
if not isinstance(other, PolicyConstraints):
|
|
794
|
+
return NotImplemented
|
|
795
|
+
|
|
796
|
+
return (
|
|
797
|
+
self.require_explicit_policy == other.require_explicit_policy
|
|
798
|
+
and self.inhibit_policy_mapping == other.inhibit_policy_mapping
|
|
799
|
+
)
|
|
800
|
+
|
|
801
|
+
def __hash__(self) -> int:
|
|
802
|
+
return hash(
|
|
803
|
+
(self.require_explicit_policy, self.inhibit_policy_mapping)
|
|
804
|
+
)
|
|
805
|
+
|
|
806
|
+
@property
|
|
807
|
+
def require_explicit_policy(self) -> int | None:
|
|
808
|
+
return self._require_explicit_policy
|
|
809
|
+
|
|
810
|
+
@property
|
|
811
|
+
def inhibit_policy_mapping(self) -> int | None:
|
|
812
|
+
return self._inhibit_policy_mapping
|
|
813
|
+
|
|
814
|
+
def public_bytes(self) -> bytes:
|
|
815
|
+
return rust_x509.encode_extension_value(self)
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
class CertificatePolicies(ExtensionType):
|
|
819
|
+
oid = ExtensionOID.CERTIFICATE_POLICIES
|
|
820
|
+
|
|
821
|
+
def __init__(self, policies: Iterable[PolicyInformation]) -> None:
|
|
822
|
+
policies = list(policies)
|
|
823
|
+
if not all(isinstance(x, PolicyInformation) for x in policies):
|
|
824
|
+
raise TypeError(
|
|
825
|
+
"Every item in the policies list must be a PolicyInformation"
|
|
826
|
+
)
|
|
827
|
+
|
|
828
|
+
self._policies = policies
|
|
829
|
+
|
|
830
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_policies")
|
|
831
|
+
|
|
832
|
+
def __repr__(self) -> str:
|
|
833
|
+
return f"<CertificatePolicies({self._policies})>"
|
|
834
|
+
|
|
835
|
+
def __eq__(self, other: object) -> bool:
|
|
836
|
+
if not isinstance(other, CertificatePolicies):
|
|
837
|
+
return NotImplemented
|
|
838
|
+
|
|
839
|
+
return self._policies == other._policies
|
|
840
|
+
|
|
841
|
+
def __hash__(self) -> int:
|
|
842
|
+
return hash(tuple(self._policies))
|
|
843
|
+
|
|
844
|
+
def public_bytes(self) -> bytes:
|
|
845
|
+
return rust_x509.encode_extension_value(self)
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
class PolicyInformation:
|
|
849
|
+
def __init__(
|
|
850
|
+
self,
|
|
851
|
+
policy_identifier: ObjectIdentifier,
|
|
852
|
+
policy_qualifiers: Iterable[str | UserNotice] | None,
|
|
853
|
+
) -> None:
|
|
854
|
+
if not isinstance(policy_identifier, ObjectIdentifier):
|
|
855
|
+
raise TypeError("policy_identifier must be an ObjectIdentifier")
|
|
856
|
+
|
|
857
|
+
self._policy_identifier = policy_identifier
|
|
858
|
+
|
|
859
|
+
if policy_qualifiers is not None:
|
|
860
|
+
policy_qualifiers = list(policy_qualifiers)
|
|
861
|
+
if not all(
|
|
862
|
+
isinstance(x, (str, UserNotice)) for x in policy_qualifiers
|
|
863
|
+
):
|
|
864
|
+
raise TypeError(
|
|
865
|
+
"policy_qualifiers must be a list of strings and/or "
|
|
866
|
+
"UserNotice objects or None"
|
|
867
|
+
)
|
|
868
|
+
|
|
869
|
+
self._policy_qualifiers = policy_qualifiers
|
|
870
|
+
|
|
871
|
+
def __repr__(self) -> str:
|
|
872
|
+
return (
|
|
873
|
+
f"<PolicyInformation(policy_identifier={self.policy_identifier}, "
|
|
874
|
+
f"policy_qualifiers={self.policy_qualifiers})>"
|
|
875
|
+
)
|
|
876
|
+
|
|
877
|
+
def __eq__(self, other: object) -> bool:
|
|
878
|
+
if not isinstance(other, PolicyInformation):
|
|
879
|
+
return NotImplemented
|
|
880
|
+
|
|
881
|
+
return (
|
|
882
|
+
self.policy_identifier == other.policy_identifier
|
|
883
|
+
and self.policy_qualifiers == other.policy_qualifiers
|
|
884
|
+
)
|
|
885
|
+
|
|
886
|
+
def __hash__(self) -> int:
|
|
887
|
+
if self.policy_qualifiers is not None:
|
|
888
|
+
pq = tuple(self.policy_qualifiers)
|
|
889
|
+
else:
|
|
890
|
+
pq = None
|
|
891
|
+
|
|
892
|
+
return hash((self.policy_identifier, pq))
|
|
893
|
+
|
|
894
|
+
@property
|
|
895
|
+
def policy_identifier(self) -> ObjectIdentifier:
|
|
896
|
+
return self._policy_identifier
|
|
897
|
+
|
|
898
|
+
@property
|
|
899
|
+
def policy_qualifiers(
|
|
900
|
+
self,
|
|
901
|
+
) -> list[str | UserNotice] | None:
|
|
902
|
+
return self._policy_qualifiers
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
class UserNotice:
|
|
906
|
+
def __init__(
|
|
907
|
+
self,
|
|
908
|
+
notice_reference: NoticeReference | None,
|
|
909
|
+
explicit_text: str | None,
|
|
910
|
+
) -> None:
|
|
911
|
+
if notice_reference and not isinstance(
|
|
912
|
+
notice_reference, NoticeReference
|
|
913
|
+
):
|
|
914
|
+
raise TypeError(
|
|
915
|
+
"notice_reference must be None or a NoticeReference"
|
|
916
|
+
)
|
|
917
|
+
|
|
918
|
+
self._notice_reference = notice_reference
|
|
919
|
+
self._explicit_text = explicit_text
|
|
920
|
+
|
|
921
|
+
def __repr__(self) -> str:
|
|
922
|
+
return (
|
|
923
|
+
f"<UserNotice(notice_reference={self.notice_reference}, "
|
|
924
|
+
f"explicit_text={self.explicit_text!r})>"
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
def __eq__(self, other: object) -> bool:
|
|
928
|
+
if not isinstance(other, UserNotice):
|
|
929
|
+
return NotImplemented
|
|
930
|
+
|
|
931
|
+
return (
|
|
932
|
+
self.notice_reference == other.notice_reference
|
|
933
|
+
and self.explicit_text == other.explicit_text
|
|
934
|
+
)
|
|
935
|
+
|
|
936
|
+
def __hash__(self) -> int:
|
|
937
|
+
return hash((self.notice_reference, self.explicit_text))
|
|
938
|
+
|
|
939
|
+
@property
|
|
940
|
+
def notice_reference(self) -> NoticeReference | None:
|
|
941
|
+
return self._notice_reference
|
|
942
|
+
|
|
943
|
+
@property
|
|
944
|
+
def explicit_text(self) -> str | None:
|
|
945
|
+
return self._explicit_text
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
class NoticeReference:
|
|
949
|
+
def __init__(
|
|
950
|
+
self,
|
|
951
|
+
organization: str | None,
|
|
952
|
+
notice_numbers: Iterable[int],
|
|
953
|
+
) -> None:
|
|
954
|
+
self._organization = organization
|
|
955
|
+
notice_numbers = list(notice_numbers)
|
|
956
|
+
if not all(isinstance(x, int) for x in notice_numbers):
|
|
957
|
+
raise TypeError("notice_numbers must be a list of integers")
|
|
958
|
+
|
|
959
|
+
self._notice_numbers = notice_numbers
|
|
960
|
+
|
|
961
|
+
def __repr__(self) -> str:
|
|
962
|
+
return (
|
|
963
|
+
f"<NoticeReference(organization={self.organization!r}, "
|
|
964
|
+
f"notice_numbers={self.notice_numbers})>"
|
|
965
|
+
)
|
|
966
|
+
|
|
967
|
+
def __eq__(self, other: object) -> bool:
|
|
968
|
+
if not isinstance(other, NoticeReference):
|
|
969
|
+
return NotImplemented
|
|
970
|
+
|
|
971
|
+
return (
|
|
972
|
+
self.organization == other.organization
|
|
973
|
+
and self.notice_numbers == other.notice_numbers
|
|
974
|
+
)
|
|
975
|
+
|
|
976
|
+
def __hash__(self) -> int:
|
|
977
|
+
return hash((self.organization, tuple(self.notice_numbers)))
|
|
978
|
+
|
|
979
|
+
@property
|
|
980
|
+
def organization(self) -> str | None:
|
|
981
|
+
return self._organization
|
|
982
|
+
|
|
983
|
+
@property
|
|
984
|
+
def notice_numbers(self) -> list[int]:
|
|
985
|
+
return self._notice_numbers
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
class ExtendedKeyUsage(ExtensionType):
|
|
989
|
+
oid = ExtensionOID.EXTENDED_KEY_USAGE
|
|
990
|
+
|
|
991
|
+
def __init__(self, usages: Iterable[ObjectIdentifier]) -> None:
|
|
992
|
+
usages = list(usages)
|
|
993
|
+
if not all(isinstance(x, ObjectIdentifier) for x in usages):
|
|
994
|
+
raise TypeError(
|
|
995
|
+
"Every item in the usages list must be an ObjectIdentifier"
|
|
996
|
+
)
|
|
997
|
+
|
|
998
|
+
self._usages = usages
|
|
999
|
+
|
|
1000
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_usages")
|
|
1001
|
+
|
|
1002
|
+
def __repr__(self) -> str:
|
|
1003
|
+
return f"<ExtendedKeyUsage({self._usages})>"
|
|
1004
|
+
|
|
1005
|
+
def __eq__(self, other: object) -> bool:
|
|
1006
|
+
if not isinstance(other, ExtendedKeyUsage):
|
|
1007
|
+
return NotImplemented
|
|
1008
|
+
|
|
1009
|
+
return self._usages == other._usages
|
|
1010
|
+
|
|
1011
|
+
def __hash__(self) -> int:
|
|
1012
|
+
return hash(tuple(self._usages))
|
|
1013
|
+
|
|
1014
|
+
def public_bytes(self) -> bytes:
|
|
1015
|
+
return rust_x509.encode_extension_value(self)
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
class OCSPNoCheck(ExtensionType):
|
|
1019
|
+
oid = ExtensionOID.OCSP_NO_CHECK
|
|
1020
|
+
|
|
1021
|
+
def __eq__(self, other: object) -> bool:
|
|
1022
|
+
if not isinstance(other, OCSPNoCheck):
|
|
1023
|
+
return NotImplemented
|
|
1024
|
+
|
|
1025
|
+
return True
|
|
1026
|
+
|
|
1027
|
+
def __hash__(self) -> int:
|
|
1028
|
+
return hash(OCSPNoCheck)
|
|
1029
|
+
|
|
1030
|
+
def __repr__(self) -> str:
|
|
1031
|
+
return "<OCSPNoCheck()>"
|
|
1032
|
+
|
|
1033
|
+
def public_bytes(self) -> bytes:
|
|
1034
|
+
return rust_x509.encode_extension_value(self)
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
class PrecertPoison(ExtensionType):
|
|
1038
|
+
oid = ExtensionOID.PRECERT_POISON
|
|
1039
|
+
|
|
1040
|
+
def __eq__(self, other: object) -> bool:
|
|
1041
|
+
if not isinstance(other, PrecertPoison):
|
|
1042
|
+
return NotImplemented
|
|
1043
|
+
|
|
1044
|
+
return True
|
|
1045
|
+
|
|
1046
|
+
def __hash__(self) -> int:
|
|
1047
|
+
return hash(PrecertPoison)
|
|
1048
|
+
|
|
1049
|
+
def __repr__(self) -> str:
|
|
1050
|
+
return "<PrecertPoison()>"
|
|
1051
|
+
|
|
1052
|
+
def public_bytes(self) -> bytes:
|
|
1053
|
+
return rust_x509.encode_extension_value(self)
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
class TLSFeature(ExtensionType):
|
|
1057
|
+
oid = ExtensionOID.TLS_FEATURE
|
|
1058
|
+
|
|
1059
|
+
def __init__(self, features: Iterable[TLSFeatureType]) -> None:
|
|
1060
|
+
features = list(features)
|
|
1061
|
+
if (
|
|
1062
|
+
not all(isinstance(x, TLSFeatureType) for x in features)
|
|
1063
|
+
or len(features) == 0
|
|
1064
|
+
):
|
|
1065
|
+
raise TypeError(
|
|
1066
|
+
"features must be a list of elements from the TLSFeatureType "
|
|
1067
|
+
"enum"
|
|
1068
|
+
)
|
|
1069
|
+
|
|
1070
|
+
self._features = features
|
|
1071
|
+
|
|
1072
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_features")
|
|
1073
|
+
|
|
1074
|
+
def __repr__(self) -> str:
|
|
1075
|
+
return f"<TLSFeature(features={self._features})>"
|
|
1076
|
+
|
|
1077
|
+
def __eq__(self, other: object) -> bool:
|
|
1078
|
+
if not isinstance(other, TLSFeature):
|
|
1079
|
+
return NotImplemented
|
|
1080
|
+
|
|
1081
|
+
return self._features == other._features
|
|
1082
|
+
|
|
1083
|
+
def __hash__(self) -> int:
|
|
1084
|
+
return hash(tuple(self._features))
|
|
1085
|
+
|
|
1086
|
+
def public_bytes(self) -> bytes:
|
|
1087
|
+
return rust_x509.encode_extension_value(self)
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
class TLSFeatureType(utils.Enum):
|
|
1091
|
+
# status_request is defined in RFC 6066 and is used for what is commonly
|
|
1092
|
+
# called OCSP Must-Staple when present in the TLS Feature extension in an
|
|
1093
|
+
# X.509 certificate.
|
|
1094
|
+
status_request = 5
|
|
1095
|
+
# status_request_v2 is defined in RFC 6961 and allows multiple OCSP
|
|
1096
|
+
# responses to be provided. It is not currently in use by clients or
|
|
1097
|
+
# servers.
|
|
1098
|
+
status_request_v2 = 17
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
_TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType}
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
class InhibitAnyPolicy(ExtensionType):
|
|
1105
|
+
oid = ExtensionOID.INHIBIT_ANY_POLICY
|
|
1106
|
+
|
|
1107
|
+
def __init__(self, skip_certs: int) -> None:
|
|
1108
|
+
if not isinstance(skip_certs, int):
|
|
1109
|
+
raise TypeError("skip_certs must be an integer")
|
|
1110
|
+
|
|
1111
|
+
if skip_certs < 0:
|
|
1112
|
+
raise ValueError("skip_certs must be a non-negative integer")
|
|
1113
|
+
|
|
1114
|
+
self._skip_certs = skip_certs
|
|
1115
|
+
|
|
1116
|
+
def __repr__(self) -> str:
|
|
1117
|
+
return f"<InhibitAnyPolicy(skip_certs={self.skip_certs})>"
|
|
1118
|
+
|
|
1119
|
+
def __eq__(self, other: object) -> bool:
|
|
1120
|
+
if not isinstance(other, InhibitAnyPolicy):
|
|
1121
|
+
return NotImplemented
|
|
1122
|
+
|
|
1123
|
+
return self.skip_certs == other.skip_certs
|
|
1124
|
+
|
|
1125
|
+
def __hash__(self) -> int:
|
|
1126
|
+
return hash(self.skip_certs)
|
|
1127
|
+
|
|
1128
|
+
@property
|
|
1129
|
+
def skip_certs(self) -> int:
|
|
1130
|
+
return self._skip_certs
|
|
1131
|
+
|
|
1132
|
+
def public_bytes(self) -> bytes:
|
|
1133
|
+
return rust_x509.encode_extension_value(self)
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
class KeyUsage(ExtensionType):
|
|
1137
|
+
oid = ExtensionOID.KEY_USAGE
|
|
1138
|
+
|
|
1139
|
+
def __init__(
|
|
1140
|
+
self,
|
|
1141
|
+
digital_signature: bool,
|
|
1142
|
+
content_commitment: bool,
|
|
1143
|
+
key_encipherment: bool,
|
|
1144
|
+
data_encipherment: bool,
|
|
1145
|
+
key_agreement: bool,
|
|
1146
|
+
key_cert_sign: bool,
|
|
1147
|
+
crl_sign: bool,
|
|
1148
|
+
encipher_only: bool,
|
|
1149
|
+
decipher_only: bool,
|
|
1150
|
+
) -> None:
|
|
1151
|
+
if not key_agreement and (encipher_only or decipher_only):
|
|
1152
|
+
raise ValueError(
|
|
1153
|
+
"encipher_only and decipher_only can only be true when "
|
|
1154
|
+
"key_agreement is true"
|
|
1155
|
+
)
|
|
1156
|
+
|
|
1157
|
+
self._digital_signature = digital_signature
|
|
1158
|
+
self._content_commitment = content_commitment
|
|
1159
|
+
self._key_encipherment = key_encipherment
|
|
1160
|
+
self._data_encipherment = data_encipherment
|
|
1161
|
+
self._key_agreement = key_agreement
|
|
1162
|
+
self._key_cert_sign = key_cert_sign
|
|
1163
|
+
self._crl_sign = crl_sign
|
|
1164
|
+
self._encipher_only = encipher_only
|
|
1165
|
+
self._decipher_only = decipher_only
|
|
1166
|
+
|
|
1167
|
+
@property
|
|
1168
|
+
def digital_signature(self) -> bool:
|
|
1169
|
+
return self._digital_signature
|
|
1170
|
+
|
|
1171
|
+
@property
|
|
1172
|
+
def content_commitment(self) -> bool:
|
|
1173
|
+
return self._content_commitment
|
|
1174
|
+
|
|
1175
|
+
@property
|
|
1176
|
+
def key_encipherment(self) -> bool:
|
|
1177
|
+
return self._key_encipherment
|
|
1178
|
+
|
|
1179
|
+
@property
|
|
1180
|
+
def data_encipherment(self) -> bool:
|
|
1181
|
+
return self._data_encipherment
|
|
1182
|
+
|
|
1183
|
+
@property
|
|
1184
|
+
def key_agreement(self) -> bool:
|
|
1185
|
+
return self._key_agreement
|
|
1186
|
+
|
|
1187
|
+
@property
|
|
1188
|
+
def key_cert_sign(self) -> bool:
|
|
1189
|
+
return self._key_cert_sign
|
|
1190
|
+
|
|
1191
|
+
@property
|
|
1192
|
+
def crl_sign(self) -> bool:
|
|
1193
|
+
return self._crl_sign
|
|
1194
|
+
|
|
1195
|
+
@property
|
|
1196
|
+
def encipher_only(self) -> bool:
|
|
1197
|
+
if not self.key_agreement:
|
|
1198
|
+
raise ValueError(
|
|
1199
|
+
"encipher_only is undefined unless key_agreement is true"
|
|
1200
|
+
)
|
|
1201
|
+
else:
|
|
1202
|
+
return self._encipher_only
|
|
1203
|
+
|
|
1204
|
+
@property
|
|
1205
|
+
def decipher_only(self) -> bool:
|
|
1206
|
+
if not self.key_agreement:
|
|
1207
|
+
raise ValueError(
|
|
1208
|
+
"decipher_only is undefined unless key_agreement is true"
|
|
1209
|
+
)
|
|
1210
|
+
else:
|
|
1211
|
+
return self._decipher_only
|
|
1212
|
+
|
|
1213
|
+
def __repr__(self) -> str:
|
|
1214
|
+
try:
|
|
1215
|
+
encipher_only = self.encipher_only
|
|
1216
|
+
decipher_only = self.decipher_only
|
|
1217
|
+
except ValueError:
|
|
1218
|
+
# Users found None confusing because even though encipher/decipher
|
|
1219
|
+
# have no meaning unless key_agreement is true, to construct an
|
|
1220
|
+
# instance of the class you still need to pass False.
|
|
1221
|
+
encipher_only = False
|
|
1222
|
+
decipher_only = False
|
|
1223
|
+
|
|
1224
|
+
return (
|
|
1225
|
+
f"<KeyUsage(digital_signature={self.digital_signature}, "
|
|
1226
|
+
f"content_commitment={self.content_commitment}, "
|
|
1227
|
+
f"key_encipherment={self.key_encipherment}, "
|
|
1228
|
+
f"data_encipherment={self.data_encipherment}, "
|
|
1229
|
+
f"key_agreement={self.key_agreement}, "
|
|
1230
|
+
f"key_cert_sign={self.key_cert_sign}, crl_sign={self.crl_sign}, "
|
|
1231
|
+
f"encipher_only={encipher_only}, decipher_only={decipher_only})>"
|
|
1232
|
+
)
|
|
1233
|
+
|
|
1234
|
+
def __eq__(self, other: object) -> bool:
|
|
1235
|
+
if not isinstance(other, KeyUsage):
|
|
1236
|
+
return NotImplemented
|
|
1237
|
+
|
|
1238
|
+
return (
|
|
1239
|
+
self.digital_signature == other.digital_signature
|
|
1240
|
+
and self.content_commitment == other.content_commitment
|
|
1241
|
+
and self.key_encipherment == other.key_encipherment
|
|
1242
|
+
and self.data_encipherment == other.data_encipherment
|
|
1243
|
+
and self.key_agreement == other.key_agreement
|
|
1244
|
+
and self.key_cert_sign == other.key_cert_sign
|
|
1245
|
+
and self.crl_sign == other.crl_sign
|
|
1246
|
+
and self._encipher_only == other._encipher_only
|
|
1247
|
+
and self._decipher_only == other._decipher_only
|
|
1248
|
+
)
|
|
1249
|
+
|
|
1250
|
+
def __hash__(self) -> int:
|
|
1251
|
+
return hash(
|
|
1252
|
+
(
|
|
1253
|
+
self.digital_signature,
|
|
1254
|
+
self.content_commitment,
|
|
1255
|
+
self.key_encipherment,
|
|
1256
|
+
self.data_encipherment,
|
|
1257
|
+
self.key_agreement,
|
|
1258
|
+
self.key_cert_sign,
|
|
1259
|
+
self.crl_sign,
|
|
1260
|
+
self._encipher_only,
|
|
1261
|
+
self._decipher_only,
|
|
1262
|
+
)
|
|
1263
|
+
)
|
|
1264
|
+
|
|
1265
|
+
def public_bytes(self) -> bytes:
|
|
1266
|
+
return rust_x509.encode_extension_value(self)
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
class PrivateKeyUsagePeriod(ExtensionType):
|
|
1270
|
+
oid = ExtensionOID.PRIVATE_KEY_USAGE_PERIOD
|
|
1271
|
+
|
|
1272
|
+
def __init__(
|
|
1273
|
+
self,
|
|
1274
|
+
not_before: datetime.datetime | None,
|
|
1275
|
+
not_after: datetime.datetime | None,
|
|
1276
|
+
) -> None:
|
|
1277
|
+
if (
|
|
1278
|
+
not isinstance(not_before, datetime.datetime)
|
|
1279
|
+
and not_before is not None
|
|
1280
|
+
):
|
|
1281
|
+
raise TypeError("not_before must be a datetime.datetime or None")
|
|
1282
|
+
|
|
1283
|
+
if (
|
|
1284
|
+
not isinstance(not_after, datetime.datetime)
|
|
1285
|
+
and not_after is not None
|
|
1286
|
+
):
|
|
1287
|
+
raise TypeError("not_after must be a datetime.datetime or None")
|
|
1288
|
+
|
|
1289
|
+
if not_before is None and not_after is None:
|
|
1290
|
+
raise ValueError(
|
|
1291
|
+
"At least one of not_before and not_after must not be None"
|
|
1292
|
+
)
|
|
1293
|
+
|
|
1294
|
+
if (
|
|
1295
|
+
not_before is not None
|
|
1296
|
+
and not_after is not None
|
|
1297
|
+
and not_before > not_after
|
|
1298
|
+
):
|
|
1299
|
+
raise ValueError("not_before must be before not_after")
|
|
1300
|
+
|
|
1301
|
+
self._not_before = not_before
|
|
1302
|
+
self._not_after = not_after
|
|
1303
|
+
|
|
1304
|
+
@property
|
|
1305
|
+
def not_before(self) -> datetime.datetime | None:
|
|
1306
|
+
return self._not_before
|
|
1307
|
+
|
|
1308
|
+
@property
|
|
1309
|
+
def not_after(self) -> datetime.datetime | None:
|
|
1310
|
+
return self._not_after
|
|
1311
|
+
|
|
1312
|
+
def __repr__(self) -> str:
|
|
1313
|
+
return (
|
|
1314
|
+
f"<PrivateKeyUsagePeriod(not_before={self.not_before}, "
|
|
1315
|
+
f"not_after={self.not_after})>"
|
|
1316
|
+
)
|
|
1317
|
+
|
|
1318
|
+
def __eq__(self, other: object) -> bool:
|
|
1319
|
+
if not isinstance(other, PrivateKeyUsagePeriod):
|
|
1320
|
+
return NotImplemented
|
|
1321
|
+
|
|
1322
|
+
return (
|
|
1323
|
+
self.not_before == other.not_before
|
|
1324
|
+
and self.not_after == other.not_after
|
|
1325
|
+
)
|
|
1326
|
+
|
|
1327
|
+
def __hash__(self) -> int:
|
|
1328
|
+
return hash((self.not_before, self.not_after))
|
|
1329
|
+
|
|
1330
|
+
def public_bytes(self) -> bytes:
|
|
1331
|
+
return rust_x509.encode_extension_value(self)
|
|
1332
|
+
|
|
1333
|
+
|
|
1334
|
+
class NameConstraints(ExtensionType):
|
|
1335
|
+
oid = ExtensionOID.NAME_CONSTRAINTS
|
|
1336
|
+
|
|
1337
|
+
def __init__(
|
|
1338
|
+
self,
|
|
1339
|
+
permitted_subtrees: Iterable[GeneralName] | None,
|
|
1340
|
+
excluded_subtrees: Iterable[GeneralName] | None,
|
|
1341
|
+
) -> None:
|
|
1342
|
+
if permitted_subtrees is not None:
|
|
1343
|
+
permitted_subtrees = list(permitted_subtrees)
|
|
1344
|
+
if not permitted_subtrees:
|
|
1345
|
+
raise ValueError(
|
|
1346
|
+
"permitted_subtrees must be a non-empty list or None"
|
|
1347
|
+
)
|
|
1348
|
+
if not all(isinstance(x, GeneralName) for x in permitted_subtrees):
|
|
1349
|
+
raise TypeError(
|
|
1350
|
+
"permitted_subtrees must be a list of GeneralName objects "
|
|
1351
|
+
"or None"
|
|
1352
|
+
)
|
|
1353
|
+
|
|
1354
|
+
self._validate_tree(permitted_subtrees)
|
|
1355
|
+
|
|
1356
|
+
if excluded_subtrees is not None:
|
|
1357
|
+
excluded_subtrees = list(excluded_subtrees)
|
|
1358
|
+
if not excluded_subtrees:
|
|
1359
|
+
raise ValueError(
|
|
1360
|
+
"excluded_subtrees must be a non-empty list or None"
|
|
1361
|
+
)
|
|
1362
|
+
if not all(isinstance(x, GeneralName) for x in excluded_subtrees):
|
|
1363
|
+
raise TypeError(
|
|
1364
|
+
"excluded_subtrees must be a list of GeneralName objects "
|
|
1365
|
+
"or None"
|
|
1366
|
+
)
|
|
1367
|
+
|
|
1368
|
+
self._validate_tree(excluded_subtrees)
|
|
1369
|
+
|
|
1370
|
+
if permitted_subtrees is None and excluded_subtrees is None:
|
|
1371
|
+
raise ValueError(
|
|
1372
|
+
"At least one of permitted_subtrees and excluded_subtrees "
|
|
1373
|
+
"must not be None"
|
|
1374
|
+
)
|
|
1375
|
+
|
|
1376
|
+
self._permitted_subtrees = permitted_subtrees
|
|
1377
|
+
self._excluded_subtrees = excluded_subtrees
|
|
1378
|
+
|
|
1379
|
+
def __eq__(self, other: object) -> bool:
|
|
1380
|
+
if not isinstance(other, NameConstraints):
|
|
1381
|
+
return NotImplemented
|
|
1382
|
+
|
|
1383
|
+
return (
|
|
1384
|
+
self.excluded_subtrees == other.excluded_subtrees
|
|
1385
|
+
and self.permitted_subtrees == other.permitted_subtrees
|
|
1386
|
+
)
|
|
1387
|
+
|
|
1388
|
+
def _validate_tree(self, tree: Iterable[GeneralName]) -> None:
|
|
1389
|
+
self._validate_ip_name(tree)
|
|
1390
|
+
self._validate_dns_name(tree)
|
|
1391
|
+
|
|
1392
|
+
def _validate_ip_name(self, tree: Iterable[GeneralName]) -> None:
|
|
1393
|
+
if any(
|
|
1394
|
+
isinstance(name, IPAddress)
|
|
1395
|
+
and not isinstance(
|
|
1396
|
+
name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
|
|
1397
|
+
)
|
|
1398
|
+
for name in tree
|
|
1399
|
+
):
|
|
1400
|
+
raise TypeError(
|
|
1401
|
+
"IPAddress name constraints must be an IPv4Network or"
|
|
1402
|
+
" IPv6Network object"
|
|
1403
|
+
)
|
|
1404
|
+
|
|
1405
|
+
def _validate_dns_name(self, tree: Iterable[GeneralName]) -> None:
|
|
1406
|
+
if any(
|
|
1407
|
+
isinstance(name, DNSName) and "*" in name.value for name in tree
|
|
1408
|
+
):
|
|
1409
|
+
raise ValueError(
|
|
1410
|
+
"DNSName name constraints must not contain the '*' wildcard"
|
|
1411
|
+
" character"
|
|
1412
|
+
)
|
|
1413
|
+
|
|
1414
|
+
def __repr__(self) -> str:
|
|
1415
|
+
return (
|
|
1416
|
+
f"<NameConstraints(permitted_subtrees={self.permitted_subtrees}, "
|
|
1417
|
+
f"excluded_subtrees={self.excluded_subtrees})>"
|
|
1418
|
+
)
|
|
1419
|
+
|
|
1420
|
+
def __hash__(self) -> int:
|
|
1421
|
+
if self.permitted_subtrees is not None:
|
|
1422
|
+
ps: tuple[GeneralName, ...] | None = tuple(self.permitted_subtrees)
|
|
1423
|
+
else:
|
|
1424
|
+
ps = None
|
|
1425
|
+
|
|
1426
|
+
if self.excluded_subtrees is not None:
|
|
1427
|
+
es: tuple[GeneralName, ...] | None = tuple(self.excluded_subtrees)
|
|
1428
|
+
else:
|
|
1429
|
+
es = None
|
|
1430
|
+
|
|
1431
|
+
return hash((ps, es))
|
|
1432
|
+
|
|
1433
|
+
@property
|
|
1434
|
+
def permitted_subtrees(
|
|
1435
|
+
self,
|
|
1436
|
+
) -> list[GeneralName] | None:
|
|
1437
|
+
return self._permitted_subtrees
|
|
1438
|
+
|
|
1439
|
+
@property
|
|
1440
|
+
def excluded_subtrees(
|
|
1441
|
+
self,
|
|
1442
|
+
) -> list[GeneralName] | None:
|
|
1443
|
+
return self._excluded_subtrees
|
|
1444
|
+
|
|
1445
|
+
def public_bytes(self) -> bytes:
|
|
1446
|
+
return rust_x509.encode_extension_value(self)
|
|
1447
|
+
|
|
1448
|
+
|
|
1449
|
+
class Extension(typing.Generic[ExtensionTypeVar]):
|
|
1450
|
+
def __init__(
|
|
1451
|
+
self, oid: ObjectIdentifier, critical: bool, value: ExtensionTypeVar
|
|
1452
|
+
) -> None:
|
|
1453
|
+
if not isinstance(oid, ObjectIdentifier):
|
|
1454
|
+
raise TypeError(
|
|
1455
|
+
"oid argument must be an ObjectIdentifier instance."
|
|
1456
|
+
)
|
|
1457
|
+
|
|
1458
|
+
if not isinstance(critical, bool):
|
|
1459
|
+
raise TypeError("critical must be a boolean value")
|
|
1460
|
+
|
|
1461
|
+
self._oid = oid
|
|
1462
|
+
self._critical = critical
|
|
1463
|
+
self._value = value
|
|
1464
|
+
|
|
1465
|
+
@property
|
|
1466
|
+
def oid(self) -> ObjectIdentifier:
|
|
1467
|
+
return self._oid
|
|
1468
|
+
|
|
1469
|
+
@property
|
|
1470
|
+
def critical(self) -> bool:
|
|
1471
|
+
return self._critical
|
|
1472
|
+
|
|
1473
|
+
@property
|
|
1474
|
+
def value(self) -> ExtensionTypeVar:
|
|
1475
|
+
return self._value
|
|
1476
|
+
|
|
1477
|
+
def __repr__(self) -> str:
|
|
1478
|
+
return (
|
|
1479
|
+
f"<Extension(oid={self.oid}, critical={self.critical}, "
|
|
1480
|
+
f"value={self.value})>"
|
|
1481
|
+
)
|
|
1482
|
+
|
|
1483
|
+
def __eq__(self, other: object) -> bool:
|
|
1484
|
+
if not isinstance(other, Extension):
|
|
1485
|
+
return NotImplemented
|
|
1486
|
+
|
|
1487
|
+
return (
|
|
1488
|
+
self.oid == other.oid
|
|
1489
|
+
and self.critical == other.critical
|
|
1490
|
+
and self.value == other.value
|
|
1491
|
+
)
|
|
1492
|
+
|
|
1493
|
+
def __hash__(self) -> int:
|
|
1494
|
+
return hash((self.oid, self.critical, self.value))
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
class GeneralNames:
|
|
1498
|
+
def __init__(self, general_names: Iterable[GeneralName]) -> None:
|
|
1499
|
+
general_names = list(general_names)
|
|
1500
|
+
if not all(isinstance(x, GeneralName) for x in general_names):
|
|
1501
|
+
raise TypeError(
|
|
1502
|
+
"Every item in the general_names list must be an "
|
|
1503
|
+
"object conforming to the GeneralName interface"
|
|
1504
|
+
)
|
|
1505
|
+
|
|
1506
|
+
self._general_names = general_names
|
|
1507
|
+
|
|
1508
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
|
|
1509
|
+
|
|
1510
|
+
@typing.overload
|
|
1511
|
+
def get_values_for_type(
|
|
1512
|
+
self,
|
|
1513
|
+
type: type[DNSName]
|
|
1514
|
+
| type[UniformResourceIdentifier]
|
|
1515
|
+
| type[RFC822Name],
|
|
1516
|
+
) -> list[str]: ...
|
|
1517
|
+
|
|
1518
|
+
@typing.overload
|
|
1519
|
+
def get_values_for_type(
|
|
1520
|
+
self,
|
|
1521
|
+
type: type[DirectoryName],
|
|
1522
|
+
) -> list[Name]: ...
|
|
1523
|
+
|
|
1524
|
+
@typing.overload
|
|
1525
|
+
def get_values_for_type(
|
|
1526
|
+
self,
|
|
1527
|
+
type: type[RegisteredID],
|
|
1528
|
+
) -> list[ObjectIdentifier]: ...
|
|
1529
|
+
|
|
1530
|
+
@typing.overload
|
|
1531
|
+
def get_values_for_type(
|
|
1532
|
+
self, type: type[IPAddress]
|
|
1533
|
+
) -> list[_IPAddressTypes]: ...
|
|
1534
|
+
|
|
1535
|
+
@typing.overload
|
|
1536
|
+
def get_values_for_type(
|
|
1537
|
+
self, type: type[OtherName]
|
|
1538
|
+
) -> list[OtherName]: ...
|
|
1539
|
+
|
|
1540
|
+
def get_values_for_type(
|
|
1541
|
+
self,
|
|
1542
|
+
type: type[DNSName]
|
|
1543
|
+
| type[DirectoryName]
|
|
1544
|
+
| type[IPAddress]
|
|
1545
|
+
| type[OtherName]
|
|
1546
|
+
| type[RFC822Name]
|
|
1547
|
+
| type[RegisteredID]
|
|
1548
|
+
| type[UniformResourceIdentifier],
|
|
1549
|
+
) -> (
|
|
1550
|
+
list[_IPAddressTypes]
|
|
1551
|
+
| list[str]
|
|
1552
|
+
| list[OtherName]
|
|
1553
|
+
| list[Name]
|
|
1554
|
+
| list[ObjectIdentifier]
|
|
1555
|
+
):
|
|
1556
|
+
# Return the value of each GeneralName, except for OtherName instances
|
|
1557
|
+
# which we return directly because it has two important properties not
|
|
1558
|
+
# just one value.
|
|
1559
|
+
objs = (i for i in self if isinstance(i, type))
|
|
1560
|
+
if type != OtherName:
|
|
1561
|
+
return [i.value for i in objs]
|
|
1562
|
+
return list(objs)
|
|
1563
|
+
|
|
1564
|
+
def __repr__(self) -> str:
|
|
1565
|
+
return f"<GeneralNames({self._general_names})>"
|
|
1566
|
+
|
|
1567
|
+
def __eq__(self, other: object) -> bool:
|
|
1568
|
+
if not isinstance(other, GeneralNames):
|
|
1569
|
+
return NotImplemented
|
|
1570
|
+
|
|
1571
|
+
return self._general_names == other._general_names
|
|
1572
|
+
|
|
1573
|
+
def __hash__(self) -> int:
|
|
1574
|
+
return hash(tuple(self._general_names))
|
|
1575
|
+
|
|
1576
|
+
|
|
1577
|
+
class SubjectAlternativeName(ExtensionType):
|
|
1578
|
+
oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME
|
|
1579
|
+
|
|
1580
|
+
def __init__(self, general_names: Iterable[GeneralName]) -> None:
|
|
1581
|
+
self._general_names = GeneralNames(general_names)
|
|
1582
|
+
|
|
1583
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
|
|
1584
|
+
|
|
1585
|
+
@typing.overload
|
|
1586
|
+
def get_values_for_type(
|
|
1587
|
+
self,
|
|
1588
|
+
type: type[DNSName]
|
|
1589
|
+
| type[UniformResourceIdentifier]
|
|
1590
|
+
| type[RFC822Name],
|
|
1591
|
+
) -> list[str]: ...
|
|
1592
|
+
|
|
1593
|
+
@typing.overload
|
|
1594
|
+
def get_values_for_type(
|
|
1595
|
+
self,
|
|
1596
|
+
type: type[DirectoryName],
|
|
1597
|
+
) -> list[Name]: ...
|
|
1598
|
+
|
|
1599
|
+
@typing.overload
|
|
1600
|
+
def get_values_for_type(
|
|
1601
|
+
self,
|
|
1602
|
+
type: type[RegisteredID],
|
|
1603
|
+
) -> list[ObjectIdentifier]: ...
|
|
1604
|
+
|
|
1605
|
+
@typing.overload
|
|
1606
|
+
def get_values_for_type(
|
|
1607
|
+
self, type: type[IPAddress]
|
|
1608
|
+
) -> list[_IPAddressTypes]: ...
|
|
1609
|
+
|
|
1610
|
+
@typing.overload
|
|
1611
|
+
def get_values_for_type(
|
|
1612
|
+
self, type: type[OtherName]
|
|
1613
|
+
) -> list[OtherName]: ...
|
|
1614
|
+
|
|
1615
|
+
def get_values_for_type(
|
|
1616
|
+
self,
|
|
1617
|
+
type: type[DNSName]
|
|
1618
|
+
| type[DirectoryName]
|
|
1619
|
+
| type[IPAddress]
|
|
1620
|
+
| type[OtherName]
|
|
1621
|
+
| type[RFC822Name]
|
|
1622
|
+
| type[RegisteredID]
|
|
1623
|
+
| type[UniformResourceIdentifier],
|
|
1624
|
+
) -> (
|
|
1625
|
+
list[_IPAddressTypes]
|
|
1626
|
+
| list[str]
|
|
1627
|
+
| list[OtherName]
|
|
1628
|
+
| list[Name]
|
|
1629
|
+
| list[ObjectIdentifier]
|
|
1630
|
+
):
|
|
1631
|
+
return self._general_names.get_values_for_type(type)
|
|
1632
|
+
|
|
1633
|
+
def __repr__(self) -> str:
|
|
1634
|
+
return f"<SubjectAlternativeName({self._general_names})>"
|
|
1635
|
+
|
|
1636
|
+
def __eq__(self, other: object) -> bool:
|
|
1637
|
+
if not isinstance(other, SubjectAlternativeName):
|
|
1638
|
+
return NotImplemented
|
|
1639
|
+
|
|
1640
|
+
return self._general_names == other._general_names
|
|
1641
|
+
|
|
1642
|
+
def __hash__(self) -> int:
|
|
1643
|
+
return hash(self._general_names)
|
|
1644
|
+
|
|
1645
|
+
def public_bytes(self) -> bytes:
|
|
1646
|
+
return rust_x509.encode_extension_value(self)
|
|
1647
|
+
|
|
1648
|
+
|
|
1649
|
+
class IssuerAlternativeName(ExtensionType):
|
|
1650
|
+
oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME
|
|
1651
|
+
|
|
1652
|
+
def __init__(self, general_names: Iterable[GeneralName]) -> None:
|
|
1653
|
+
self._general_names = GeneralNames(general_names)
|
|
1654
|
+
|
|
1655
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
|
|
1656
|
+
|
|
1657
|
+
@typing.overload
|
|
1658
|
+
def get_values_for_type(
|
|
1659
|
+
self,
|
|
1660
|
+
type: type[DNSName]
|
|
1661
|
+
| type[UniformResourceIdentifier]
|
|
1662
|
+
| type[RFC822Name],
|
|
1663
|
+
) -> list[str]: ...
|
|
1664
|
+
|
|
1665
|
+
@typing.overload
|
|
1666
|
+
def get_values_for_type(
|
|
1667
|
+
self,
|
|
1668
|
+
type: type[DirectoryName],
|
|
1669
|
+
) -> list[Name]: ...
|
|
1670
|
+
|
|
1671
|
+
@typing.overload
|
|
1672
|
+
def get_values_for_type(
|
|
1673
|
+
self,
|
|
1674
|
+
type: type[RegisteredID],
|
|
1675
|
+
) -> list[ObjectIdentifier]: ...
|
|
1676
|
+
|
|
1677
|
+
@typing.overload
|
|
1678
|
+
def get_values_for_type(
|
|
1679
|
+
self, type: type[IPAddress]
|
|
1680
|
+
) -> list[_IPAddressTypes]: ...
|
|
1681
|
+
|
|
1682
|
+
@typing.overload
|
|
1683
|
+
def get_values_for_type(
|
|
1684
|
+
self, type: type[OtherName]
|
|
1685
|
+
) -> list[OtherName]: ...
|
|
1686
|
+
|
|
1687
|
+
def get_values_for_type(
|
|
1688
|
+
self,
|
|
1689
|
+
type: type[DNSName]
|
|
1690
|
+
| type[DirectoryName]
|
|
1691
|
+
| type[IPAddress]
|
|
1692
|
+
| type[OtherName]
|
|
1693
|
+
| type[RFC822Name]
|
|
1694
|
+
| type[RegisteredID]
|
|
1695
|
+
| type[UniformResourceIdentifier],
|
|
1696
|
+
) -> (
|
|
1697
|
+
list[_IPAddressTypes]
|
|
1698
|
+
| list[str]
|
|
1699
|
+
| list[OtherName]
|
|
1700
|
+
| list[Name]
|
|
1701
|
+
| list[ObjectIdentifier]
|
|
1702
|
+
):
|
|
1703
|
+
return self._general_names.get_values_for_type(type)
|
|
1704
|
+
|
|
1705
|
+
def __repr__(self) -> str:
|
|
1706
|
+
return f"<IssuerAlternativeName({self._general_names})>"
|
|
1707
|
+
|
|
1708
|
+
def __eq__(self, other: object) -> bool:
|
|
1709
|
+
if not isinstance(other, IssuerAlternativeName):
|
|
1710
|
+
return NotImplemented
|
|
1711
|
+
|
|
1712
|
+
return self._general_names == other._general_names
|
|
1713
|
+
|
|
1714
|
+
def __hash__(self) -> int:
|
|
1715
|
+
return hash(self._general_names)
|
|
1716
|
+
|
|
1717
|
+
def public_bytes(self) -> bytes:
|
|
1718
|
+
return rust_x509.encode_extension_value(self)
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
class CertificateIssuer(ExtensionType):
|
|
1722
|
+
oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER
|
|
1723
|
+
|
|
1724
|
+
def __init__(self, general_names: Iterable[GeneralName]) -> None:
|
|
1725
|
+
self._general_names = GeneralNames(general_names)
|
|
1726
|
+
|
|
1727
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
|
|
1728
|
+
|
|
1729
|
+
@typing.overload
|
|
1730
|
+
def get_values_for_type(
|
|
1731
|
+
self,
|
|
1732
|
+
type: type[DNSName]
|
|
1733
|
+
| type[UniformResourceIdentifier]
|
|
1734
|
+
| type[RFC822Name],
|
|
1735
|
+
) -> list[str]: ...
|
|
1736
|
+
|
|
1737
|
+
@typing.overload
|
|
1738
|
+
def get_values_for_type(
|
|
1739
|
+
self,
|
|
1740
|
+
type: type[DirectoryName],
|
|
1741
|
+
) -> list[Name]: ...
|
|
1742
|
+
|
|
1743
|
+
@typing.overload
|
|
1744
|
+
def get_values_for_type(
|
|
1745
|
+
self,
|
|
1746
|
+
type: type[RegisteredID],
|
|
1747
|
+
) -> list[ObjectIdentifier]: ...
|
|
1748
|
+
|
|
1749
|
+
@typing.overload
|
|
1750
|
+
def get_values_for_type(
|
|
1751
|
+
self, type: type[IPAddress]
|
|
1752
|
+
) -> list[_IPAddressTypes]: ...
|
|
1753
|
+
|
|
1754
|
+
@typing.overload
|
|
1755
|
+
def get_values_for_type(
|
|
1756
|
+
self, type: type[OtherName]
|
|
1757
|
+
) -> list[OtherName]: ...
|
|
1758
|
+
|
|
1759
|
+
def get_values_for_type(
|
|
1760
|
+
self,
|
|
1761
|
+
type: type[DNSName]
|
|
1762
|
+
| type[DirectoryName]
|
|
1763
|
+
| type[IPAddress]
|
|
1764
|
+
| type[OtherName]
|
|
1765
|
+
| type[RFC822Name]
|
|
1766
|
+
| type[RegisteredID]
|
|
1767
|
+
| type[UniformResourceIdentifier],
|
|
1768
|
+
) -> (
|
|
1769
|
+
list[_IPAddressTypes]
|
|
1770
|
+
| list[str]
|
|
1771
|
+
| list[OtherName]
|
|
1772
|
+
| list[Name]
|
|
1773
|
+
| list[ObjectIdentifier]
|
|
1774
|
+
):
|
|
1775
|
+
return self._general_names.get_values_for_type(type)
|
|
1776
|
+
|
|
1777
|
+
def __repr__(self) -> str:
|
|
1778
|
+
return f"<CertificateIssuer({self._general_names})>"
|
|
1779
|
+
|
|
1780
|
+
def __eq__(self, other: object) -> bool:
|
|
1781
|
+
if not isinstance(other, CertificateIssuer):
|
|
1782
|
+
return NotImplemented
|
|
1783
|
+
|
|
1784
|
+
return self._general_names == other._general_names
|
|
1785
|
+
|
|
1786
|
+
def __hash__(self) -> int:
|
|
1787
|
+
return hash(self._general_names)
|
|
1788
|
+
|
|
1789
|
+
def public_bytes(self) -> bytes:
|
|
1790
|
+
return rust_x509.encode_extension_value(self)
|
|
1791
|
+
|
|
1792
|
+
|
|
1793
|
+
class CRLReason(ExtensionType):
|
|
1794
|
+
oid = CRLEntryExtensionOID.CRL_REASON
|
|
1795
|
+
|
|
1796
|
+
def __init__(self, reason: ReasonFlags) -> None:
|
|
1797
|
+
if not isinstance(reason, ReasonFlags):
|
|
1798
|
+
raise TypeError("reason must be an element from ReasonFlags")
|
|
1799
|
+
|
|
1800
|
+
self._reason = reason
|
|
1801
|
+
|
|
1802
|
+
def __repr__(self) -> str:
|
|
1803
|
+
return f"<CRLReason(reason={self._reason})>"
|
|
1804
|
+
|
|
1805
|
+
def __eq__(self, other: object) -> bool:
|
|
1806
|
+
if not isinstance(other, CRLReason):
|
|
1807
|
+
return NotImplemented
|
|
1808
|
+
|
|
1809
|
+
return self.reason == other.reason
|
|
1810
|
+
|
|
1811
|
+
def __hash__(self) -> int:
|
|
1812
|
+
return hash(self.reason)
|
|
1813
|
+
|
|
1814
|
+
@property
|
|
1815
|
+
def reason(self) -> ReasonFlags:
|
|
1816
|
+
return self._reason
|
|
1817
|
+
|
|
1818
|
+
def public_bytes(self) -> bytes:
|
|
1819
|
+
return rust_x509.encode_extension_value(self)
|
|
1820
|
+
|
|
1821
|
+
|
|
1822
|
+
class InvalidityDate(ExtensionType):
|
|
1823
|
+
oid = CRLEntryExtensionOID.INVALIDITY_DATE
|
|
1824
|
+
|
|
1825
|
+
def __init__(self, invalidity_date: datetime.datetime) -> None:
|
|
1826
|
+
if not isinstance(invalidity_date, datetime.datetime):
|
|
1827
|
+
raise TypeError("invalidity_date must be a datetime.datetime")
|
|
1828
|
+
|
|
1829
|
+
self._invalidity_date = invalidity_date
|
|
1830
|
+
|
|
1831
|
+
def __repr__(self) -> str:
|
|
1832
|
+
return f"<InvalidityDate(invalidity_date={self._invalidity_date})>"
|
|
1833
|
+
|
|
1834
|
+
def __eq__(self, other: object) -> bool:
|
|
1835
|
+
if not isinstance(other, InvalidityDate):
|
|
1836
|
+
return NotImplemented
|
|
1837
|
+
|
|
1838
|
+
return self.invalidity_date == other.invalidity_date
|
|
1839
|
+
|
|
1840
|
+
def __hash__(self) -> int:
|
|
1841
|
+
return hash(self.invalidity_date)
|
|
1842
|
+
|
|
1843
|
+
@property
|
|
1844
|
+
def invalidity_date(self) -> datetime.datetime:
|
|
1845
|
+
return self._invalidity_date
|
|
1846
|
+
|
|
1847
|
+
@property
|
|
1848
|
+
def invalidity_date_utc(self) -> datetime.datetime:
|
|
1849
|
+
if self._invalidity_date.tzinfo is None:
|
|
1850
|
+
return self._invalidity_date.replace(tzinfo=datetime.timezone.utc)
|
|
1851
|
+
else:
|
|
1852
|
+
return self._invalidity_date.astimezone(tz=datetime.timezone.utc)
|
|
1853
|
+
|
|
1854
|
+
def public_bytes(self) -> bytes:
|
|
1855
|
+
return rust_x509.encode_extension_value(self)
|
|
1856
|
+
|
|
1857
|
+
|
|
1858
|
+
class PrecertificateSignedCertificateTimestamps(ExtensionType):
|
|
1859
|
+
oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
|
|
1860
|
+
|
|
1861
|
+
def __init__(
|
|
1862
|
+
self,
|
|
1863
|
+
signed_certificate_timestamps: Iterable[SignedCertificateTimestamp],
|
|
1864
|
+
) -> None:
|
|
1865
|
+
signed_certificate_timestamps = list(signed_certificate_timestamps)
|
|
1866
|
+
if not all(
|
|
1867
|
+
isinstance(sct, SignedCertificateTimestamp)
|
|
1868
|
+
for sct in signed_certificate_timestamps
|
|
1869
|
+
):
|
|
1870
|
+
raise TypeError(
|
|
1871
|
+
"Every item in the signed_certificate_timestamps list must be "
|
|
1872
|
+
"a SignedCertificateTimestamp"
|
|
1873
|
+
)
|
|
1874
|
+
self._signed_certificate_timestamps = signed_certificate_timestamps
|
|
1875
|
+
|
|
1876
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods(
|
|
1877
|
+
"_signed_certificate_timestamps"
|
|
1878
|
+
)
|
|
1879
|
+
|
|
1880
|
+
def __repr__(self) -> str:
|
|
1881
|
+
return f"<PrecertificateSignedCertificateTimestamps({list(self)})>"
|
|
1882
|
+
|
|
1883
|
+
def __hash__(self) -> int:
|
|
1884
|
+
return hash(tuple(self._signed_certificate_timestamps))
|
|
1885
|
+
|
|
1886
|
+
def __eq__(self, other: object) -> bool:
|
|
1887
|
+
if not isinstance(other, PrecertificateSignedCertificateTimestamps):
|
|
1888
|
+
return NotImplemented
|
|
1889
|
+
|
|
1890
|
+
return (
|
|
1891
|
+
self._signed_certificate_timestamps
|
|
1892
|
+
== other._signed_certificate_timestamps
|
|
1893
|
+
)
|
|
1894
|
+
|
|
1895
|
+
def public_bytes(self) -> bytes:
|
|
1896
|
+
return rust_x509.encode_extension_value(self)
|
|
1897
|
+
|
|
1898
|
+
|
|
1899
|
+
class SignedCertificateTimestamps(ExtensionType):
|
|
1900
|
+
oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS
|
|
1901
|
+
|
|
1902
|
+
def __init__(
|
|
1903
|
+
self,
|
|
1904
|
+
signed_certificate_timestamps: Iterable[SignedCertificateTimestamp],
|
|
1905
|
+
) -> None:
|
|
1906
|
+
signed_certificate_timestamps = list(signed_certificate_timestamps)
|
|
1907
|
+
if not all(
|
|
1908
|
+
isinstance(sct, SignedCertificateTimestamp)
|
|
1909
|
+
for sct in signed_certificate_timestamps
|
|
1910
|
+
):
|
|
1911
|
+
raise TypeError(
|
|
1912
|
+
"Every item in the signed_certificate_timestamps list must be "
|
|
1913
|
+
"a SignedCertificateTimestamp"
|
|
1914
|
+
)
|
|
1915
|
+
self._signed_certificate_timestamps = signed_certificate_timestamps
|
|
1916
|
+
|
|
1917
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods(
|
|
1918
|
+
"_signed_certificate_timestamps"
|
|
1919
|
+
)
|
|
1920
|
+
|
|
1921
|
+
def __repr__(self) -> str:
|
|
1922
|
+
return f"<SignedCertificateTimestamps({list(self)})>"
|
|
1923
|
+
|
|
1924
|
+
def __hash__(self) -> int:
|
|
1925
|
+
return hash(tuple(self._signed_certificate_timestamps))
|
|
1926
|
+
|
|
1927
|
+
def __eq__(self, other: object) -> bool:
|
|
1928
|
+
if not isinstance(other, SignedCertificateTimestamps):
|
|
1929
|
+
return NotImplemented
|
|
1930
|
+
|
|
1931
|
+
return (
|
|
1932
|
+
self._signed_certificate_timestamps
|
|
1933
|
+
== other._signed_certificate_timestamps
|
|
1934
|
+
)
|
|
1935
|
+
|
|
1936
|
+
def public_bytes(self) -> bytes:
|
|
1937
|
+
return rust_x509.encode_extension_value(self)
|
|
1938
|
+
|
|
1939
|
+
|
|
1940
|
+
class OCSPNonce(ExtensionType):
|
|
1941
|
+
oid = OCSPExtensionOID.NONCE
|
|
1942
|
+
|
|
1943
|
+
def __init__(self, nonce: bytes) -> None:
|
|
1944
|
+
if not isinstance(nonce, bytes):
|
|
1945
|
+
raise TypeError("nonce must be bytes")
|
|
1946
|
+
|
|
1947
|
+
self._nonce = nonce
|
|
1948
|
+
|
|
1949
|
+
def __eq__(self, other: object) -> bool:
|
|
1950
|
+
if not isinstance(other, OCSPNonce):
|
|
1951
|
+
return NotImplemented
|
|
1952
|
+
|
|
1953
|
+
return self.nonce == other.nonce
|
|
1954
|
+
|
|
1955
|
+
def __hash__(self) -> int:
|
|
1956
|
+
return hash(self.nonce)
|
|
1957
|
+
|
|
1958
|
+
def __repr__(self) -> str:
|
|
1959
|
+
return f"<OCSPNonce(nonce={self.nonce!r})>"
|
|
1960
|
+
|
|
1961
|
+
@property
|
|
1962
|
+
def nonce(self) -> bytes:
|
|
1963
|
+
return self._nonce
|
|
1964
|
+
|
|
1965
|
+
def public_bytes(self) -> bytes:
|
|
1966
|
+
return rust_x509.encode_extension_value(self)
|
|
1967
|
+
|
|
1968
|
+
|
|
1969
|
+
class OCSPAcceptableResponses(ExtensionType):
|
|
1970
|
+
oid = OCSPExtensionOID.ACCEPTABLE_RESPONSES
|
|
1971
|
+
|
|
1972
|
+
def __init__(self, responses: Iterable[ObjectIdentifier]) -> None:
|
|
1973
|
+
responses = list(responses)
|
|
1974
|
+
if any(not isinstance(r, ObjectIdentifier) for r in responses):
|
|
1975
|
+
raise TypeError("All responses must be ObjectIdentifiers")
|
|
1976
|
+
|
|
1977
|
+
self._responses = responses
|
|
1978
|
+
|
|
1979
|
+
def __eq__(self, other: object) -> bool:
|
|
1980
|
+
if not isinstance(other, OCSPAcceptableResponses):
|
|
1981
|
+
return NotImplemented
|
|
1982
|
+
|
|
1983
|
+
return self._responses == other._responses
|
|
1984
|
+
|
|
1985
|
+
def __hash__(self) -> int:
|
|
1986
|
+
return hash(tuple(self._responses))
|
|
1987
|
+
|
|
1988
|
+
def __repr__(self) -> str:
|
|
1989
|
+
return f"<OCSPAcceptableResponses(responses={self._responses})>"
|
|
1990
|
+
|
|
1991
|
+
def __iter__(self) -> Iterator[ObjectIdentifier]:
|
|
1992
|
+
return iter(self._responses)
|
|
1993
|
+
|
|
1994
|
+
def public_bytes(self) -> bytes:
|
|
1995
|
+
return rust_x509.encode_extension_value(self)
|
|
1996
|
+
|
|
1997
|
+
|
|
1998
|
+
class IssuingDistributionPoint(ExtensionType):
|
|
1999
|
+
oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT
|
|
2000
|
+
|
|
2001
|
+
def __init__(
|
|
2002
|
+
self,
|
|
2003
|
+
full_name: Iterable[GeneralName] | None,
|
|
2004
|
+
relative_name: RelativeDistinguishedName | None,
|
|
2005
|
+
only_contains_user_certs: bool,
|
|
2006
|
+
only_contains_ca_certs: bool,
|
|
2007
|
+
only_some_reasons: frozenset[ReasonFlags] | None,
|
|
2008
|
+
indirect_crl: bool,
|
|
2009
|
+
only_contains_attribute_certs: bool,
|
|
2010
|
+
) -> None:
|
|
2011
|
+
if full_name is not None:
|
|
2012
|
+
full_name = list(full_name)
|
|
2013
|
+
|
|
2014
|
+
if only_some_reasons and (
|
|
2015
|
+
not isinstance(only_some_reasons, frozenset)
|
|
2016
|
+
or not all(isinstance(x, ReasonFlags) for x in only_some_reasons)
|
|
2017
|
+
):
|
|
2018
|
+
raise TypeError(
|
|
2019
|
+
"only_some_reasons must be None or frozenset of ReasonFlags"
|
|
2020
|
+
)
|
|
2021
|
+
|
|
2022
|
+
if only_some_reasons and (
|
|
2023
|
+
ReasonFlags.unspecified in only_some_reasons
|
|
2024
|
+
or ReasonFlags.remove_from_crl in only_some_reasons
|
|
2025
|
+
):
|
|
2026
|
+
raise ValueError(
|
|
2027
|
+
"unspecified and remove_from_crl are not valid reasons in an "
|
|
2028
|
+
"IssuingDistributionPoint"
|
|
2029
|
+
)
|
|
2030
|
+
|
|
2031
|
+
if not (
|
|
2032
|
+
isinstance(only_contains_user_certs, bool)
|
|
2033
|
+
and isinstance(only_contains_ca_certs, bool)
|
|
2034
|
+
and isinstance(indirect_crl, bool)
|
|
2035
|
+
and isinstance(only_contains_attribute_certs, bool)
|
|
2036
|
+
):
|
|
2037
|
+
raise TypeError(
|
|
2038
|
+
"only_contains_user_certs, only_contains_ca_certs, "
|
|
2039
|
+
"indirect_crl and only_contains_attribute_certs "
|
|
2040
|
+
"must all be boolean."
|
|
2041
|
+
)
|
|
2042
|
+
|
|
2043
|
+
# Per RFC5280 Section 5.2.5, the Issuing Distribution Point extension
|
|
2044
|
+
# in a CRL can have only one of onlyContainsUserCerts,
|
|
2045
|
+
# onlyContainsCACerts, onlyContainsAttributeCerts set to TRUE.
|
|
2046
|
+
crl_constraints = [
|
|
2047
|
+
only_contains_user_certs,
|
|
2048
|
+
only_contains_ca_certs,
|
|
2049
|
+
only_contains_attribute_certs,
|
|
2050
|
+
]
|
|
2051
|
+
|
|
2052
|
+
if len([x for x in crl_constraints if x]) > 1:
|
|
2053
|
+
raise ValueError(
|
|
2054
|
+
"Only one of the following can be set to True: "
|
|
2055
|
+
"only_contains_user_certs, only_contains_ca_certs, "
|
|
2056
|
+
"only_contains_attribute_certs"
|
|
2057
|
+
)
|
|
2058
|
+
|
|
2059
|
+
if not any(
|
|
2060
|
+
[
|
|
2061
|
+
only_contains_user_certs,
|
|
2062
|
+
only_contains_ca_certs,
|
|
2063
|
+
indirect_crl,
|
|
2064
|
+
only_contains_attribute_certs,
|
|
2065
|
+
full_name,
|
|
2066
|
+
relative_name,
|
|
2067
|
+
only_some_reasons,
|
|
2068
|
+
]
|
|
2069
|
+
):
|
|
2070
|
+
raise ValueError(
|
|
2071
|
+
"Cannot create empty extension: "
|
|
2072
|
+
"if only_contains_user_certs, only_contains_ca_certs, "
|
|
2073
|
+
"indirect_crl, and only_contains_attribute_certs are all False"
|
|
2074
|
+
", then either full_name, relative_name, or only_some_reasons "
|
|
2075
|
+
"must have a value."
|
|
2076
|
+
)
|
|
2077
|
+
|
|
2078
|
+
self._only_contains_user_certs = only_contains_user_certs
|
|
2079
|
+
self._only_contains_ca_certs = only_contains_ca_certs
|
|
2080
|
+
self._indirect_crl = indirect_crl
|
|
2081
|
+
self._only_contains_attribute_certs = only_contains_attribute_certs
|
|
2082
|
+
self._only_some_reasons = only_some_reasons
|
|
2083
|
+
self._full_name = full_name
|
|
2084
|
+
self._relative_name = relative_name
|
|
2085
|
+
|
|
2086
|
+
def __repr__(self) -> str:
|
|
2087
|
+
return (
|
|
2088
|
+
f"<IssuingDistributionPoint(full_name={self.full_name}, "
|
|
2089
|
+
f"relative_name={self.relative_name}, "
|
|
2090
|
+
f"only_contains_user_certs={self.only_contains_user_certs}, "
|
|
2091
|
+
f"only_contains_ca_certs={self.only_contains_ca_certs}, "
|
|
2092
|
+
f"only_some_reasons={self.only_some_reasons}, "
|
|
2093
|
+
f"indirect_crl={self.indirect_crl}, "
|
|
2094
|
+
"only_contains_attribute_certs="
|
|
2095
|
+
f"{self.only_contains_attribute_certs})>"
|
|
2096
|
+
)
|
|
2097
|
+
|
|
2098
|
+
def __eq__(self, other: object) -> bool:
|
|
2099
|
+
if not isinstance(other, IssuingDistributionPoint):
|
|
2100
|
+
return NotImplemented
|
|
2101
|
+
|
|
2102
|
+
return (
|
|
2103
|
+
self.full_name == other.full_name
|
|
2104
|
+
and self.relative_name == other.relative_name
|
|
2105
|
+
and self.only_contains_user_certs == other.only_contains_user_certs
|
|
2106
|
+
and self.only_contains_ca_certs == other.only_contains_ca_certs
|
|
2107
|
+
and self.only_some_reasons == other.only_some_reasons
|
|
2108
|
+
and self.indirect_crl == other.indirect_crl
|
|
2109
|
+
and self.only_contains_attribute_certs
|
|
2110
|
+
== other.only_contains_attribute_certs
|
|
2111
|
+
)
|
|
2112
|
+
|
|
2113
|
+
def __hash__(self) -> int:
|
|
2114
|
+
return hash(
|
|
2115
|
+
(
|
|
2116
|
+
self.full_name,
|
|
2117
|
+
self.relative_name,
|
|
2118
|
+
self.only_contains_user_certs,
|
|
2119
|
+
self.only_contains_ca_certs,
|
|
2120
|
+
self.only_some_reasons,
|
|
2121
|
+
self.indirect_crl,
|
|
2122
|
+
self.only_contains_attribute_certs,
|
|
2123
|
+
)
|
|
2124
|
+
)
|
|
2125
|
+
|
|
2126
|
+
@property
|
|
2127
|
+
def full_name(self) -> list[GeneralName] | None:
|
|
2128
|
+
return self._full_name
|
|
2129
|
+
|
|
2130
|
+
@property
|
|
2131
|
+
def relative_name(self) -> RelativeDistinguishedName | None:
|
|
2132
|
+
return self._relative_name
|
|
2133
|
+
|
|
2134
|
+
@property
|
|
2135
|
+
def only_contains_user_certs(self) -> bool:
|
|
2136
|
+
return self._only_contains_user_certs
|
|
2137
|
+
|
|
2138
|
+
@property
|
|
2139
|
+
def only_contains_ca_certs(self) -> bool:
|
|
2140
|
+
return self._only_contains_ca_certs
|
|
2141
|
+
|
|
2142
|
+
@property
|
|
2143
|
+
def only_some_reasons(
|
|
2144
|
+
self,
|
|
2145
|
+
) -> frozenset[ReasonFlags] | None:
|
|
2146
|
+
return self._only_some_reasons
|
|
2147
|
+
|
|
2148
|
+
@property
|
|
2149
|
+
def indirect_crl(self) -> bool:
|
|
2150
|
+
return self._indirect_crl
|
|
2151
|
+
|
|
2152
|
+
@property
|
|
2153
|
+
def only_contains_attribute_certs(self) -> bool:
|
|
2154
|
+
return self._only_contains_attribute_certs
|
|
2155
|
+
|
|
2156
|
+
def public_bytes(self) -> bytes:
|
|
2157
|
+
return rust_x509.encode_extension_value(self)
|
|
2158
|
+
|
|
2159
|
+
|
|
2160
|
+
class MSCertificateTemplate(ExtensionType):
|
|
2161
|
+
oid = ExtensionOID.MS_CERTIFICATE_TEMPLATE
|
|
2162
|
+
|
|
2163
|
+
def __init__(
|
|
2164
|
+
self,
|
|
2165
|
+
template_id: ObjectIdentifier,
|
|
2166
|
+
major_version: int | None,
|
|
2167
|
+
minor_version: int | None,
|
|
2168
|
+
) -> None:
|
|
2169
|
+
if not isinstance(template_id, ObjectIdentifier):
|
|
2170
|
+
raise TypeError("oid must be an ObjectIdentifier")
|
|
2171
|
+
self._template_id = template_id
|
|
2172
|
+
if (
|
|
2173
|
+
major_version is not None and not isinstance(major_version, int)
|
|
2174
|
+
) or (
|
|
2175
|
+
minor_version is not None and not isinstance(minor_version, int)
|
|
2176
|
+
):
|
|
2177
|
+
raise TypeError(
|
|
2178
|
+
"major_version and minor_version must be integers or None"
|
|
2179
|
+
)
|
|
2180
|
+
self._major_version = major_version
|
|
2181
|
+
self._minor_version = minor_version
|
|
2182
|
+
|
|
2183
|
+
@property
|
|
2184
|
+
def template_id(self) -> ObjectIdentifier:
|
|
2185
|
+
return self._template_id
|
|
2186
|
+
|
|
2187
|
+
@property
|
|
2188
|
+
def major_version(self) -> int | None:
|
|
2189
|
+
return self._major_version
|
|
2190
|
+
|
|
2191
|
+
@property
|
|
2192
|
+
def minor_version(self) -> int | None:
|
|
2193
|
+
return self._minor_version
|
|
2194
|
+
|
|
2195
|
+
def __repr__(self) -> str:
|
|
2196
|
+
return (
|
|
2197
|
+
f"<MSCertificateTemplate(template_id={self.template_id}, "
|
|
2198
|
+
f"major_version={self.major_version}, "
|
|
2199
|
+
f"minor_version={self.minor_version})>"
|
|
2200
|
+
)
|
|
2201
|
+
|
|
2202
|
+
def __eq__(self, other: object) -> bool:
|
|
2203
|
+
if not isinstance(other, MSCertificateTemplate):
|
|
2204
|
+
return NotImplemented
|
|
2205
|
+
|
|
2206
|
+
return (
|
|
2207
|
+
self.template_id == other.template_id
|
|
2208
|
+
and self.major_version == other.major_version
|
|
2209
|
+
and self.minor_version == other.minor_version
|
|
2210
|
+
)
|
|
2211
|
+
|
|
2212
|
+
def __hash__(self) -> int:
|
|
2213
|
+
return hash((self.template_id, self.major_version, self.minor_version))
|
|
2214
|
+
|
|
2215
|
+
def public_bytes(self) -> bytes:
|
|
2216
|
+
return rust_x509.encode_extension_value(self)
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
class NamingAuthority:
|
|
2220
|
+
def __init__(
|
|
2221
|
+
self,
|
|
2222
|
+
id: ObjectIdentifier | None,
|
|
2223
|
+
url: str | None,
|
|
2224
|
+
text: str | None,
|
|
2225
|
+
) -> None:
|
|
2226
|
+
if id is not None and not isinstance(id, ObjectIdentifier):
|
|
2227
|
+
raise TypeError("id must be an ObjectIdentifier")
|
|
2228
|
+
|
|
2229
|
+
if url is not None and not isinstance(url, str):
|
|
2230
|
+
raise TypeError("url must be a str")
|
|
2231
|
+
|
|
2232
|
+
if text is not None and not isinstance(text, str):
|
|
2233
|
+
raise TypeError("text must be a str")
|
|
2234
|
+
|
|
2235
|
+
self._id = id
|
|
2236
|
+
self._url = url
|
|
2237
|
+
self._text = text
|
|
2238
|
+
|
|
2239
|
+
@property
|
|
2240
|
+
def id(self) -> ObjectIdentifier | None:
|
|
2241
|
+
return self._id
|
|
2242
|
+
|
|
2243
|
+
@property
|
|
2244
|
+
def url(self) -> str | None:
|
|
2245
|
+
return self._url
|
|
2246
|
+
|
|
2247
|
+
@property
|
|
2248
|
+
def text(self) -> str | None:
|
|
2249
|
+
return self._text
|
|
2250
|
+
|
|
2251
|
+
def __repr__(self) -> str:
|
|
2252
|
+
return (
|
|
2253
|
+
f"<NamingAuthority("
|
|
2254
|
+
f"id={self.id}, url={self.url}, text={self.text})>"
|
|
2255
|
+
)
|
|
2256
|
+
|
|
2257
|
+
def __eq__(self, other: object) -> bool:
|
|
2258
|
+
if not isinstance(other, NamingAuthority):
|
|
2259
|
+
return NotImplemented
|
|
2260
|
+
|
|
2261
|
+
return (
|
|
2262
|
+
self.id == other.id
|
|
2263
|
+
and self.url == other.url
|
|
2264
|
+
and self.text == other.text
|
|
2265
|
+
)
|
|
2266
|
+
|
|
2267
|
+
def __hash__(self) -> int:
|
|
2268
|
+
return hash(
|
|
2269
|
+
(
|
|
2270
|
+
self.id,
|
|
2271
|
+
self.url,
|
|
2272
|
+
self.text,
|
|
2273
|
+
)
|
|
2274
|
+
)
|
|
2275
|
+
|
|
2276
|
+
|
|
2277
|
+
class ProfessionInfo:
|
|
2278
|
+
def __init__(
|
|
2279
|
+
self,
|
|
2280
|
+
naming_authority: NamingAuthority | None,
|
|
2281
|
+
profession_items: Iterable[str],
|
|
2282
|
+
profession_oids: Iterable[ObjectIdentifier] | None,
|
|
2283
|
+
registration_number: str | None,
|
|
2284
|
+
add_profession_info: bytes | None,
|
|
2285
|
+
) -> None:
|
|
2286
|
+
if naming_authority is not None and not isinstance(
|
|
2287
|
+
naming_authority, NamingAuthority
|
|
2288
|
+
):
|
|
2289
|
+
raise TypeError("naming_authority must be a NamingAuthority")
|
|
2290
|
+
|
|
2291
|
+
profession_items = list(profession_items)
|
|
2292
|
+
if not all(isinstance(item, str) for item in profession_items):
|
|
2293
|
+
raise TypeError(
|
|
2294
|
+
"Every item in the profession_items list must be a str"
|
|
2295
|
+
)
|
|
2296
|
+
|
|
2297
|
+
if profession_oids is not None:
|
|
2298
|
+
profession_oids = list(profession_oids)
|
|
2299
|
+
if not all(
|
|
2300
|
+
isinstance(oid, ObjectIdentifier) for oid in profession_oids
|
|
2301
|
+
):
|
|
2302
|
+
raise TypeError(
|
|
2303
|
+
"Every item in the profession_oids list must be an "
|
|
2304
|
+
"ObjectIdentifier"
|
|
2305
|
+
)
|
|
2306
|
+
|
|
2307
|
+
if registration_number is not None and not isinstance(
|
|
2308
|
+
registration_number, str
|
|
2309
|
+
):
|
|
2310
|
+
raise TypeError("registration_number must be a str")
|
|
2311
|
+
|
|
2312
|
+
if add_profession_info is not None and not isinstance(
|
|
2313
|
+
add_profession_info, bytes
|
|
2314
|
+
):
|
|
2315
|
+
raise TypeError("add_profession_info must be bytes")
|
|
2316
|
+
|
|
2317
|
+
self._naming_authority = naming_authority
|
|
2318
|
+
self._profession_items = profession_items
|
|
2319
|
+
self._profession_oids = profession_oids
|
|
2320
|
+
self._registration_number = registration_number
|
|
2321
|
+
self._add_profession_info = add_profession_info
|
|
2322
|
+
|
|
2323
|
+
@property
|
|
2324
|
+
def naming_authority(self) -> NamingAuthority | None:
|
|
2325
|
+
return self._naming_authority
|
|
2326
|
+
|
|
2327
|
+
@property
|
|
2328
|
+
def profession_items(self) -> list[str]:
|
|
2329
|
+
return self._profession_items
|
|
2330
|
+
|
|
2331
|
+
@property
|
|
2332
|
+
def profession_oids(self) -> list[ObjectIdentifier] | None:
|
|
2333
|
+
return self._profession_oids
|
|
2334
|
+
|
|
2335
|
+
@property
|
|
2336
|
+
def registration_number(self) -> str | None:
|
|
2337
|
+
return self._registration_number
|
|
2338
|
+
|
|
2339
|
+
@property
|
|
2340
|
+
def add_profession_info(self) -> bytes | None:
|
|
2341
|
+
return self._add_profession_info
|
|
2342
|
+
|
|
2343
|
+
def __repr__(self) -> str:
|
|
2344
|
+
return (
|
|
2345
|
+
f"<ProfessionInfo(naming_authority={self.naming_authority}, "
|
|
2346
|
+
f"profession_items={self.profession_items}, "
|
|
2347
|
+
f"profession_oids={self.profession_oids}, "
|
|
2348
|
+
f"registration_number={self.registration_number}, "
|
|
2349
|
+
f"add_profession_info={self.add_profession_info!r})>"
|
|
2350
|
+
)
|
|
2351
|
+
|
|
2352
|
+
def __eq__(self, other: object) -> bool:
|
|
2353
|
+
if not isinstance(other, ProfessionInfo):
|
|
2354
|
+
return NotImplemented
|
|
2355
|
+
|
|
2356
|
+
return (
|
|
2357
|
+
self.naming_authority == other.naming_authority
|
|
2358
|
+
and self.profession_items == other.profession_items
|
|
2359
|
+
and self.profession_oids == other.profession_oids
|
|
2360
|
+
and self.registration_number == other.registration_number
|
|
2361
|
+
and self.add_profession_info == other.add_profession_info
|
|
2362
|
+
)
|
|
2363
|
+
|
|
2364
|
+
def __hash__(self) -> int:
|
|
2365
|
+
if self.profession_oids is not None:
|
|
2366
|
+
profession_oids = tuple(self.profession_oids)
|
|
2367
|
+
else:
|
|
2368
|
+
profession_oids = None
|
|
2369
|
+
return hash(
|
|
2370
|
+
(
|
|
2371
|
+
self.naming_authority,
|
|
2372
|
+
tuple(self.profession_items),
|
|
2373
|
+
profession_oids,
|
|
2374
|
+
self.registration_number,
|
|
2375
|
+
self.add_profession_info,
|
|
2376
|
+
)
|
|
2377
|
+
)
|
|
2378
|
+
|
|
2379
|
+
|
|
2380
|
+
class Admission:
|
|
2381
|
+
def __init__(
|
|
2382
|
+
self,
|
|
2383
|
+
admission_authority: GeneralName | None,
|
|
2384
|
+
naming_authority: NamingAuthority | None,
|
|
2385
|
+
profession_infos: Iterable[ProfessionInfo],
|
|
2386
|
+
) -> None:
|
|
2387
|
+
if admission_authority is not None and not isinstance(
|
|
2388
|
+
admission_authority, GeneralName
|
|
2389
|
+
):
|
|
2390
|
+
raise TypeError("admission_authority must be a GeneralName")
|
|
2391
|
+
|
|
2392
|
+
if naming_authority is not None and not isinstance(
|
|
2393
|
+
naming_authority, NamingAuthority
|
|
2394
|
+
):
|
|
2395
|
+
raise TypeError("naming_authority must be a NamingAuthority")
|
|
2396
|
+
|
|
2397
|
+
profession_infos = list(profession_infos)
|
|
2398
|
+
if not all(
|
|
2399
|
+
isinstance(info, ProfessionInfo) for info in profession_infos
|
|
2400
|
+
):
|
|
2401
|
+
raise TypeError(
|
|
2402
|
+
"Every item in the profession_infos list must be a "
|
|
2403
|
+
"ProfessionInfo"
|
|
2404
|
+
)
|
|
2405
|
+
|
|
2406
|
+
self._admission_authority = admission_authority
|
|
2407
|
+
self._naming_authority = naming_authority
|
|
2408
|
+
self._profession_infos = profession_infos
|
|
2409
|
+
|
|
2410
|
+
@property
|
|
2411
|
+
def admission_authority(self) -> GeneralName | None:
|
|
2412
|
+
return self._admission_authority
|
|
2413
|
+
|
|
2414
|
+
@property
|
|
2415
|
+
def naming_authority(self) -> NamingAuthority | None:
|
|
2416
|
+
return self._naming_authority
|
|
2417
|
+
|
|
2418
|
+
@property
|
|
2419
|
+
def profession_infos(self) -> list[ProfessionInfo]:
|
|
2420
|
+
return self._profession_infos
|
|
2421
|
+
|
|
2422
|
+
def __repr__(self) -> str:
|
|
2423
|
+
return (
|
|
2424
|
+
f"<Admission(admission_authority={self.admission_authority}, "
|
|
2425
|
+
f"naming_authority={self.naming_authority}, "
|
|
2426
|
+
f"profession_infos={self.profession_infos})>"
|
|
2427
|
+
)
|
|
2428
|
+
|
|
2429
|
+
def __eq__(self, other: object) -> bool:
|
|
2430
|
+
if not isinstance(other, Admission):
|
|
2431
|
+
return NotImplemented
|
|
2432
|
+
|
|
2433
|
+
return (
|
|
2434
|
+
self.admission_authority == other.admission_authority
|
|
2435
|
+
and self.naming_authority == other.naming_authority
|
|
2436
|
+
and self.profession_infos == other.profession_infos
|
|
2437
|
+
)
|
|
2438
|
+
|
|
2439
|
+
def __hash__(self) -> int:
|
|
2440
|
+
return hash(
|
|
2441
|
+
(
|
|
2442
|
+
self.admission_authority,
|
|
2443
|
+
self.naming_authority,
|
|
2444
|
+
tuple(self.profession_infos),
|
|
2445
|
+
)
|
|
2446
|
+
)
|
|
2447
|
+
|
|
2448
|
+
|
|
2449
|
+
class Admissions(ExtensionType):
|
|
2450
|
+
oid = ExtensionOID.ADMISSIONS
|
|
2451
|
+
|
|
2452
|
+
def __init__(
|
|
2453
|
+
self,
|
|
2454
|
+
authority: GeneralName | None,
|
|
2455
|
+
admissions: Iterable[Admission],
|
|
2456
|
+
) -> None:
|
|
2457
|
+
if authority is not None and not isinstance(authority, GeneralName):
|
|
2458
|
+
raise TypeError("authority must be a GeneralName")
|
|
2459
|
+
|
|
2460
|
+
admissions = list(admissions)
|
|
2461
|
+
if not all(
|
|
2462
|
+
isinstance(admission, Admission) for admission in admissions
|
|
2463
|
+
):
|
|
2464
|
+
raise TypeError(
|
|
2465
|
+
"Every item in the contents_of_admissions list must be an "
|
|
2466
|
+
"Admission"
|
|
2467
|
+
)
|
|
2468
|
+
|
|
2469
|
+
self._authority = authority
|
|
2470
|
+
self._admissions = admissions
|
|
2471
|
+
|
|
2472
|
+
__len__, __iter__, __getitem__ = _make_sequence_methods("_admissions")
|
|
2473
|
+
|
|
2474
|
+
@property
|
|
2475
|
+
def authority(self) -> GeneralName | None:
|
|
2476
|
+
return self._authority
|
|
2477
|
+
|
|
2478
|
+
def __repr__(self) -> str:
|
|
2479
|
+
return (
|
|
2480
|
+
f"<Admissions(authority={self._authority}, "
|
|
2481
|
+
f"admissions={self._admissions})>"
|
|
2482
|
+
)
|
|
2483
|
+
|
|
2484
|
+
def __eq__(self, other: object) -> bool:
|
|
2485
|
+
if not isinstance(other, Admissions):
|
|
2486
|
+
return NotImplemented
|
|
2487
|
+
|
|
2488
|
+
return (
|
|
2489
|
+
self.authority == other.authority
|
|
2490
|
+
and self._admissions == other._admissions
|
|
2491
|
+
)
|
|
2492
|
+
|
|
2493
|
+
def __hash__(self) -> int:
|
|
2494
|
+
return hash((self.authority, tuple(self._admissions)))
|
|
2495
|
+
|
|
2496
|
+
def public_bytes(self) -> bytes:
|
|
2497
|
+
return rust_x509.encode_extension_value(self)
|
|
2498
|
+
|
|
2499
|
+
|
|
2500
|
+
class UnrecognizedExtension(ExtensionType):
|
|
2501
|
+
def __init__(self, oid: ObjectIdentifier, value: bytes) -> None:
|
|
2502
|
+
if not isinstance(oid, ObjectIdentifier):
|
|
2503
|
+
raise TypeError("oid must be an ObjectIdentifier")
|
|
2504
|
+
self._oid = oid
|
|
2505
|
+
self._value = value
|
|
2506
|
+
|
|
2507
|
+
@property
|
|
2508
|
+
def oid(self) -> ObjectIdentifier: # type: ignore[override]
|
|
2509
|
+
return self._oid
|
|
2510
|
+
|
|
2511
|
+
@property
|
|
2512
|
+
def value(self) -> bytes:
|
|
2513
|
+
return self._value
|
|
2514
|
+
|
|
2515
|
+
def __repr__(self) -> str:
|
|
2516
|
+
return f"<UnrecognizedExtension(oid={self.oid}, value={self.value!r})>"
|
|
2517
|
+
|
|
2518
|
+
def __eq__(self, other: object) -> bool:
|
|
2519
|
+
if not isinstance(other, UnrecognizedExtension):
|
|
2520
|
+
return NotImplemented
|
|
2521
|
+
|
|
2522
|
+
return self.oid == other.oid and self.value == other.value
|
|
2523
|
+
|
|
2524
|
+
def __hash__(self) -> int:
|
|
2525
|
+
return hash((self.oid, self.value))
|
|
2526
|
+
|
|
2527
|
+
def public_bytes(self) -> bytes:
|
|
2528
|
+
return self.value
|