cert-utils 0.1.18__tar.gz → 0.2.0__tar.gz
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.
- cert_utils-0.2.0/CHANGES.txt +60 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/PKG-INFO +4 -4
- {cert_utils-0.1.18 → cert_utils-0.2.0}/README.md +3 -2
- cert_utils-0.2.0/pyproject.toml +2 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/setup.cfg +7 -1
- {cert_utils-0.1.18 → cert_utils-0.2.0}/setup.py +1 -17
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/__init__.py +3 -1
- cert_utils-0.2.0/src/cert_utils/compat/cryptography.py +168 -0
- cert_utils-0.2.0/src/cert_utils/compat/deprecated.py +24 -0
- cert_utils-0.2.0/src/cert_utils/compat/openssl.py +701 -0
- cert_utils-0.2.0/src/cert_utils/compat/pyopenssl.py +206 -0
- cert_utils-0.2.0/src/cert_utils/conditionals.py +74 -0
- cert_utils-0.2.0/src/cert_utils/convert.py +308 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/core.py +464 -1651
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/errors.py +19 -1
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt_info.py +1 -1
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/model.py +40 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/scripts/cert_info.py +3 -0
- cert_utils-0.2.0/src/cert_utils/utils.py +335 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils.egg-info/PKG-INFO +4 -4
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils.egg-info/SOURCES.txt +10 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils.egg-info/requires.txt +1 -3
- cert_utils-0.2.0/tests/test_data/draft-acme-ari/cert--all.pem +10 -0
- cert_utils-0.2.0/tests/test_data/draft-acme-ari/cert--issuer+serial.pem +9 -0
- cert_utils-0.2.0/tests/test_data/draft-acme-ari/cert--key_id.pem +9 -0
- cert_utils-0.2.0/tests/test_data/draft-acme-ari/edge_case_generate.py +123 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_unit.py +191 -299
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tox.ini +3 -1
- cert_utils-0.1.18/CHANGES.txt +0 -38
- cert_utils-0.1.18/pyproject.toml +0 -2
- cert_utils-0.1.18/src/cert_utils/utils.py +0 -103
- {cert_utils-0.1.18 → cert_utils-0.2.0}/LICENSE.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/MANIFEST.in +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e5-cross.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e5.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e6-cross.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e6.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e7-cross.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e7.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e8-cross.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e8.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e9-cross.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/e9.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/fakeleintermediatex1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/fakelerootx1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/isrg-root-ocsp-x1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/isrg-root-x1-cross-signed.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/isrg-root-x2-cross-signed.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/isrg-root-x2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/isrgrootx1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/isrgrootx1.pkix +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-e1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-e2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-r3-cross-signed.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-r3.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-r4-cross-signed.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-r4.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-x1-cross-signed.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-x2-cross-signed.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-x3-cross-signed.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/lets-encrypt-x4-cross-signed.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/letsencryptauthorityx1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/letsencryptauthorityx2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/letsencryptauthorityx3.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/letsencryptauthorityx4.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/r10.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/r11.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/r12.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/r13.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/r14.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/trustid-x3-root.p7c +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/letsencrypt-certs/trustid-x3-root.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils/py.typed +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils.egg-info/dependency_links.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils.egg-info/entry_points.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils.egg-info/not-zip-safe +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/src/cert_utils.egg-info/top_level.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/__init__.py +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/_utils.py +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/__README__.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/__README__.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/alternate_chains/1/chain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/alternate_chains/1/fullchain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/alternate_chains/2/chain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/alternate_chains/2/fullchain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/cert.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/chain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/fullchain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/alternate_chains/1/privkey.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/draft-acme-ari/appendix_a-cert.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-ec/ec384-1-key.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-ec/ec384-1.csr +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-ec/ec384-2-key.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-3.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-4.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-5.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-cycle-account_daily.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-cycle-account_weekly.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-cycle-global_daily.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-cycle-global_weekly.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/AcmeAccountKey-cycle-single_certificate.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/acme_account_1.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/acme_account_2.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/acme_account_3.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/acme_account_4.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/acme_account_5.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/private_1.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/private_2.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/private_3.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/private_4.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/private_5.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_1-server.crt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_1-server.csr +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_1-server.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_2-server.crt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_2-server.csr +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_2-server.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_3-server.crt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_3-server.csr +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_3-server.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_4-server.crt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_4-server.csr +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_4-server.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_5-server.crt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_5-server.csr +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/key_technology-rsa/selfsigned_5-server.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/__README__.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/_data.json +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/_demo.py +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/cert.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/chain_0.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/chain_0_bad.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/chain_1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/chain_2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/root_0.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/root_1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/TestA/root_2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/long_chains/__README__.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/cert1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/cert2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/cert3.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/cert4.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/cert5.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/cert6.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/chain1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/chain2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/chain3.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/chain4.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/chain5.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/chain6.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/fullchain1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/fullchain2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/fullchain3.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/fullchain4.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/fullchain5.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/fullchain6.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/privkey1.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/privkey2.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/privkey3.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/privkey4.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/privkey5.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/pebble-certs/privkey6.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/_support/account.key +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/_support/info.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/account_001/info.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/account_001/meta.json +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/account_001/private_key.json +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/account_001/private_key.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/account_001/regr.json +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_001/cert.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_001/chain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_001/csr.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_001/fullchain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_001/info.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_001/privkey.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_001/test.py +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_002/csr.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_002/info.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_002/privkey.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_003/cert.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_003/csr.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_003/fullchain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_003/info.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_003/privkey.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_004/cert.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_004/csr.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_004/fullchain.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_004/info.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_004/privkey.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_005/csr.pem +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_005/info.txt +0 -0
- {cert_utils-0.1.18 → cert_utils-0.2.0}/tests/test_data/unit_tests/cert_005/privkey.pem +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
0.2.0
|
|
2
|
+
* replaced pyopenssl with cryptography.
|
|
3
|
+
pyopenssl was originally used because certbot required it and this package
|
|
4
|
+
was originally developed to troubleshoot certbot installations;
|
|
5
|
+
however certbot uses cryptography, so we can consider that to be available
|
|
6
|
+
and it is the officially preferred interface by both projects and the psf.
|
|
7
|
+
* split the package into multiple files
|
|
8
|
+
this is for internal use and organization is subject to change.
|
|
9
|
+
please access the main namespace.
|
|
10
|
+
* dropped Python3.6
|
|
11
|
+
this package requires cryptography>=42.0.0, specifically for chain verification
|
|
12
|
+
cryptography dropped Python3.6 in v41.0.0
|
|
13
|
+
|
|
14
|
+
0.1.9
|
|
15
|
+
pulled ari serial_no decoder into a separate unction
|
|
16
|
+
parsing akid defensively against edge case variants:
|
|
17
|
+
in web pki it is almost always "keyid:"
|
|
18
|
+
however the rfc allows for "uri:"+"serial:",
|
|
19
|
+
either in addition to keyid or replacing it
|
|
20
|
+
this should be the final release in the 0.1.x branch;
|
|
21
|
+
work has been started for 0.2.0, which will migrate away from openssl
|
|
22
|
+
|
|
23
|
+
0.1.8
|
|
24
|
+
added cert_info cli tool
|
|
25
|
+
|
|
26
|
+
0.1.7
|
|
27
|
+
ARI support
|
|
28
|
+
* ari_construct_identifier()
|
|
29
|
+
added `serial` to parse_cert dicts
|
|
30
|
+
testing on py13
|
|
31
|
+
|
|
32
|
+
0.1.6
|
|
33
|
+
updated LetsEncrypt data
|
|
34
|
+
|
|
35
|
+
0.1.5 [deleted from PyPi]
|
|
36
|
+
updated typing and tests
|
|
37
|
+
updated LetsEncrypt data
|
|
38
|
+
|
|
39
|
+
0.1.4
|
|
40
|
+
updated typing for dependencies
|
|
41
|
+
|
|
42
|
+
0.1.3
|
|
43
|
+
new mypy version caught an issue
|
|
44
|
+
|
|
45
|
+
0.1.2
|
|
46
|
+
docs improvements
|
|
47
|
+
raise a new `FallbackError_FilepathRequired` exception when missing a
|
|
48
|
+
required fallback filepath
|
|
49
|
+
|
|
50
|
+
0.1.1
|
|
51
|
+
minor formatting
|
|
52
|
+
Conditional Imports
|
|
53
|
+
imports are tried "one at a time"; not "all or nothing".
|
|
54
|
+
functions that use imports should test for all necessary options
|
|
55
|
+
new extended tests for lacking specific libraries
|
|
56
|
+
tests now monitor logs to ensure fallback behavior is triggered correctly
|
|
57
|
+
|
|
58
|
+
0.1.0
|
|
59
|
+
initial release
|
|
60
|
+
forked from peter_sslers
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cert_utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: TLS/SSL Certiicate Utilities
|
|
5
5
|
Home-page: https://github.com/aptise/cert_utils
|
|
6
6
|
Author: Jonathan Vanasco
|
|
@@ -11,7 +11,6 @@ Platform: UNKNOWN
|
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
12
|
Classifier: Programming Language :: Python
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.7
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.8
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.9
|
|
@@ -31,12 +30,13 @@ cert_utils
|
|
|
31
30
|
==========
|
|
32
31
|
|
|
33
32
|
**cert_utils** offers support for common operations when dealing with SSL
|
|
34
|
-
Certificates within the LetsEncrypt ecosystem.
|
|
33
|
+
Certificates, specifically within the LetsEncrypt ecosystem.
|
|
35
34
|
|
|
36
35
|
This library was originally developed as a toolkit for bugfixing and
|
|
37
36
|
troubleshooting large ACME installations.
|
|
38
37
|
|
|
39
|
-
**cert_utils** will attempt to process operations with Python
|
|
38
|
+
**cert_utils** will attempt to process operations with Python via the modern
|
|
39
|
+
[Cryptography](https://cryptography.io/en/latest/) package when possible.
|
|
40
40
|
If the required Python libraries are not installed, it will fallback to using
|
|
41
41
|
OpenSSL commandline via subprocesses. **cert_utils** does a bit of work to
|
|
42
42
|
standardize certificate operations across versions of Python and OpenSSL that
|
|
@@ -4,12 +4,13 @@ cert_utils
|
|
|
4
4
|
==========
|
|
5
5
|
|
|
6
6
|
**cert_utils** offers support for common operations when dealing with SSL
|
|
7
|
-
Certificates within the LetsEncrypt ecosystem.
|
|
7
|
+
Certificates, specifically within the LetsEncrypt ecosystem.
|
|
8
8
|
|
|
9
9
|
This library was originally developed as a toolkit for bugfixing and
|
|
10
10
|
troubleshooting large ACME installations.
|
|
11
11
|
|
|
12
|
-
**cert_utils** will attempt to process operations with Python
|
|
12
|
+
**cert_utils** will attempt to process operations with Python via the modern
|
|
13
|
+
[Cryptography](https://cryptography.io/en/latest/) package when possible.
|
|
13
14
|
If the required Python libraries are not installed, it will fallback to using
|
|
14
15
|
OpenSSL commandline via subprocesses. **cert_utils** does a bit of work to
|
|
15
16
|
standardize certificate operations across versions of Python and OpenSSL that
|
|
@@ -8,9 +8,15 @@ import_order_style = appnexus
|
|
|
8
8
|
per-file-ignores =
|
|
9
9
|
setup.py: E501
|
|
10
10
|
src/cert_utils/core.py: E501
|
|
11
|
+
src/cert_utils/compat/cryptography.py: E501
|
|
12
|
+
src/cert_utils/compat/openssl.py: E501
|
|
13
|
+
src/cert_utils/compat/pyopenssl.py: E501
|
|
14
|
+
src/cert_utils/conditionals.py: E501
|
|
15
|
+
src/cert_utils/convert.py: E501
|
|
11
16
|
src/cert_utils/letsencrypt_info.py: E501
|
|
17
|
+
src/cert_utils/model.py: E501
|
|
18
|
+
src/cert_utils/scripts/cert_info.py: E501
|
|
12
19
|
src/cert_utils/utils.py: E203, E501
|
|
13
|
-
|
|
14
20
|
tests/_utils.py: E501
|
|
15
21
|
tests/test_data/long_chains/TestA/_demo.py: E501
|
|
16
22
|
tests/test_unit.py: E501, F841
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"""
|
|
3
3
|
import os
|
|
4
4
|
import re
|
|
5
|
-
import sys
|
|
6
5
|
|
|
7
6
|
from setuptools import find_packages
|
|
8
7
|
from setuptools import setup
|
|
@@ -26,7 +25,7 @@ requires = [
|
|
|
26
25
|
]
|
|
27
26
|
tests_require = [
|
|
28
27
|
"certbot",
|
|
29
|
-
"cryptography",
|
|
28
|
+
"cryptography>=42.0.0",
|
|
30
29
|
"josepy",
|
|
31
30
|
"mypy",
|
|
32
31
|
"pytest",
|
|
@@ -35,20 +34,6 @@ tests_require = [
|
|
|
35
34
|
"types-requests",
|
|
36
35
|
]
|
|
37
36
|
|
|
38
|
-
# PyOpenSSL Version Pinning
|
|
39
|
-
# 23.1.0 is a bad release, see
|
|
40
|
-
# https://github.com/pyca/pyopenssl/issues/1199
|
|
41
|
-
if (sys.version_info.major == 3) and (sys.version_info.minor == 6):
|
|
42
|
-
# PyOpenSSl 23.2.0 introduces a backwards incompatible change
|
|
43
|
-
# Invalid versions are now rejected in OpenSSL.crypto.X509Req.set_version.
|
|
44
|
-
# The `acme` package (via Certbot) ends support for py3.6 on version `v1.23.0`
|
|
45
|
-
# v1.23.0 calls make_csr with a bad version, and does not pin PyOpenSSL
|
|
46
|
-
tests_require.append("PyOpenSSL>=17.5.0,!=23.1.0,<23.2.0")
|
|
47
|
-
tests_require.append("types-PyOpenSSL>=17.5.0,!=23.1.0,<23.2.0")
|
|
48
|
-
else:
|
|
49
|
-
tests_require.append("PyOpenSSL>=17.5.0,!=23.1.0")
|
|
50
|
-
tests_require.append("types-PyOpenSSL>=17.5.0,!=23.1.0")
|
|
51
|
-
|
|
52
37
|
testing_extras = tests_require + []
|
|
53
38
|
|
|
54
39
|
setup(
|
|
@@ -79,7 +64,6 @@ setup(
|
|
|
79
64
|
"Intended Audience :: Developers",
|
|
80
65
|
"Programming Language :: Python",
|
|
81
66
|
"Programming Language :: Python :: 3",
|
|
82
|
-
"Programming Language :: Python :: 3.6",
|
|
83
67
|
"Programming Language :: Python :: 3.7",
|
|
84
68
|
"Programming Language :: Python :: 3.8",
|
|
85
69
|
"Programming Language :: Python :: 3.9",
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# stdlib
|
|
2
|
+
import base64
|
|
3
|
+
import binascii
|
|
4
|
+
import hashlib
|
|
5
|
+
from typing import List
|
|
6
|
+
from typing import Optional
|
|
7
|
+
from typing import Tuple
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
from typing import Union
|
|
10
|
+
|
|
11
|
+
# locals
|
|
12
|
+
from .. import conditionals
|
|
13
|
+
from ..utils import CERT_PEM_REGEX
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from cryptography.x509 import Certificate
|
|
17
|
+
from cryptography.x509 import CertificateSigningRequest
|
|
18
|
+
from cryptography.x509.name import Name
|
|
19
|
+
from ..core import _TYPES_CRYPTOGRAPHY_PUBLICKEY
|
|
20
|
+
from ..core import _TYPES_CRYPTOGRAPHY_KEYS
|
|
21
|
+
from ..core import _TYPES_CRYPTOGRAPHY_PUBLICKEY_EXTENDED
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ==============================================================================
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _format_cryptography_components(
|
|
28
|
+
x509_name: "Name",
|
|
29
|
+
) -> str:
|
|
30
|
+
"""
|
|
31
|
+
:param data: input
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
`get_components()` is somewhat structured
|
|
35
|
+
the following are valid:
|
|
36
|
+
* [('CN', 'Pebble Intermediate CA 601ea1')]
|
|
37
|
+
* [('C', 'US'), ('O', 'Internet Security Research Group'), ('CN', 'ISRG Root X2')]
|
|
38
|
+
* [('C', 'US'), ('O', 'Internet Security Research Group'), ('CN', 'ISRG Root X1')]
|
|
39
|
+
* [('O', 'Digital Signature Trust Co.'), ('CN', 'DST Root CA X3')]
|
|
40
|
+
cert = openssl_crypto.load_certificate(openssl_crypto.FILETYPE_PEM, cert_pem)
|
|
41
|
+
_issuer = cert.get_issuer().get_components()
|
|
42
|
+
_subject = cert.get_subject().get_components()
|
|
43
|
+
"""
|
|
44
|
+
# ";".join(["%s=%s" % (i[0], i[1]) for i in x509_name])
|
|
45
|
+
_out = []
|
|
46
|
+
for attr in x509_name:
|
|
47
|
+
_converted = [i.decode("utf8") if isinstance(i, bytes) else i for i in (attr.rfc4514_attribute_name, attr.value)] # type: ignore[attr-defined]
|
|
48
|
+
_out.append("=".join(_converted))
|
|
49
|
+
out = "\n".join(_out).strip()
|
|
50
|
+
return out
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _cryptography__public_key_technology(
|
|
54
|
+
publickey: "_TYPES_CRYPTOGRAPHY_PUBLICKEY",
|
|
55
|
+
) -> Optional[str]:
|
|
56
|
+
"""
|
|
57
|
+
:param key: key object
|
|
58
|
+
:type key: instance of
|
|
59
|
+
:returns: type of key: RSA, EC, DSA
|
|
60
|
+
:rtype: str
|
|
61
|
+
"""
|
|
62
|
+
if TYPE_CHECKING:
|
|
63
|
+
assert conditionals.crypto_rsa is not None
|
|
64
|
+
assert conditionals.crypto_ec is not None
|
|
65
|
+
if isinstance(publickey, conditionals.crypto_rsa.RSAPublicKey):
|
|
66
|
+
return "RSA"
|
|
67
|
+
elif isinstance(publickey, conditionals.crypto_ec.EllipticCurvePublicKey):
|
|
68
|
+
return "EC"
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _cryptography__public_key_spki_sha256(
|
|
73
|
+
cryptography_publickey: Union[
|
|
74
|
+
"_TYPES_CRYPTOGRAPHY_KEYS", "_TYPES_CRYPTOGRAPHY_PUBLICKEY_EXTENDED"
|
|
75
|
+
],
|
|
76
|
+
as_b64: Optional[bool] = None,
|
|
77
|
+
) -> str:
|
|
78
|
+
"""
|
|
79
|
+
:param cryptography_publickey: a PublicKey from the cryptography package
|
|
80
|
+
:type cryptography_publickey: cryptography.hazmat.backends.openssl.rsa._RSAPublicKey
|
|
81
|
+
:param as_b64: Should the result be returned in Base64 encoding? default None
|
|
82
|
+
:type as_b64: boolean
|
|
83
|
+
:returns: spki_sha256
|
|
84
|
+
:rtype: str
|
|
85
|
+
"""
|
|
86
|
+
assert (
|
|
87
|
+
conditionals.crypto_serialization is not None
|
|
88
|
+
) # nest under `if TYPE_CHECKING` not needed
|
|
89
|
+
_public_bytes = cryptography_publickey.public_bytes( # type: ignore[union-attr]
|
|
90
|
+
conditionals.crypto_serialization.Encoding.DER,
|
|
91
|
+
conditionals.crypto_serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
92
|
+
)
|
|
93
|
+
spki_sha256 = hashlib.sha256(_public_bytes).digest()
|
|
94
|
+
if as_b64:
|
|
95
|
+
spki_sha256 = base64.b64encode(spki_sha256)
|
|
96
|
+
else:
|
|
97
|
+
spki_sha256 = binascii.b2a_hex(spki_sha256)
|
|
98
|
+
spki_sha256 = spki_sha256.upper()
|
|
99
|
+
_spki_sha256 = spki_sha256.decode("utf8")
|
|
100
|
+
return _spki_sha256
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _cryptography__cert_or_req__all_names(
|
|
104
|
+
loaded_cert_or_req: Union["Certificate", "CertificateSigningRequest"],
|
|
105
|
+
) -> List[str]:
|
|
106
|
+
assert conditionals.cryptography is not None
|
|
107
|
+
cn: Optional[str] = None
|
|
108
|
+
try:
|
|
109
|
+
_cn = loaded_cert_or_req.subject.get_attributes_for_oid(
|
|
110
|
+
conditionals.cryptography.x509.oid.NameOID.COMMON_NAME
|
|
111
|
+
)[0].value
|
|
112
|
+
cn = _cn.decode() if isinstance(_cn, bytes) else _cn
|
|
113
|
+
except IndexError:
|
|
114
|
+
pass
|
|
115
|
+
sans: List[str] = []
|
|
116
|
+
try:
|
|
117
|
+
ext = loaded_cert_or_req.extensions.get_extension_for_oid(
|
|
118
|
+
conditionals.cryptography.x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME
|
|
119
|
+
)
|
|
120
|
+
_sans = ext.value.get_values_for_type(conditionals.cryptography.x509.DNSName) # type: ignore[attr-defined]
|
|
121
|
+
sans = [san.decode() if isinstance(san, bytes) else san for san in _sans]
|
|
122
|
+
|
|
123
|
+
except conditionals.cryptography.x509.ExtensionNotFound:
|
|
124
|
+
pass
|
|
125
|
+
if cn is None:
|
|
126
|
+
return sans
|
|
127
|
+
return [cn] + [d for d in sans if d != cn]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def cryptography__cert_and_chain_from_fullchain(fullchain_pem: str) -> Tuple[str, str]:
|
|
131
|
+
"""Split fullchain_pem into cert_pem and chain_pem
|
|
132
|
+
|
|
133
|
+
:param str fullchain_pem: concatenated cert + chain
|
|
134
|
+
|
|
135
|
+
:returns: tuple of string cert_pem and chain_pem
|
|
136
|
+
:rtype: tuple
|
|
137
|
+
|
|
138
|
+
:raises errors.Error: If there are less than 2 certificates in the chain.
|
|
139
|
+
|
|
140
|
+
"""
|
|
141
|
+
# First pass: find the boundary of each certificate in the chain.
|
|
142
|
+
# TODO: This will silently skip over any "explanatory text" in between boundaries,
|
|
143
|
+
# which is prohibited by RFC8555.
|
|
144
|
+
if TYPE_CHECKING:
|
|
145
|
+
assert conditionals.cryptography is not None
|
|
146
|
+
assert conditionals.crypto_serialization is not None
|
|
147
|
+
|
|
148
|
+
certs = CERT_PEM_REGEX.findall(fullchain_pem)
|
|
149
|
+
if len(certs) < 2:
|
|
150
|
+
raise ValueError(
|
|
151
|
+
"failed to parse fullchain into cert and chain: "
|
|
152
|
+
+ "less than 2 certificates in chain"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Second pass: for each certificate found, parse it using OpenSSL and re-encode it,
|
|
156
|
+
# with the effect of normalizing any encoding variations (e.g. CRLF, whitespace).
|
|
157
|
+
certs_normalized = []
|
|
158
|
+
for cert_pem in certs:
|
|
159
|
+
cert = conditionals.cryptography.x509.load_pem_x509_certificate(
|
|
160
|
+
cert_pem.encode()
|
|
161
|
+
)
|
|
162
|
+
cert_pem = cert.public_bytes(
|
|
163
|
+
conditionals.crypto_serialization.Encoding.PEM
|
|
164
|
+
).decode()
|
|
165
|
+
certs_normalized.append(cert_pem)
|
|
166
|
+
|
|
167
|
+
# Since each normalized cert has a newline suffix, no extra newlines are required.
|
|
168
|
+
return (certs_normalized[0], "".join(certs_normalized[1:]))
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# local
|
|
2
|
+
from ..errors import OpenSslError
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _cleanup_openssl_md5(data: bytes) -> str:
|
|
9
|
+
"""
|
|
10
|
+
some versions of openssl handle the md5 as:
|
|
11
|
+
'1231231231'
|
|
12
|
+
others handle as
|
|
13
|
+
"(stdin)= 123123'
|
|
14
|
+
"""
|
|
15
|
+
data = data.strip()
|
|
16
|
+
data_str = data.decode("utf8")
|
|
17
|
+
if len(data_str) == 32 and (data_str[:9] != "(stdin)= "):
|
|
18
|
+
return data_str
|
|
19
|
+
if data_str[:9] != "(stdin)= " or not data_str:
|
|
20
|
+
raise OpenSslError("error reading md5 (i)")
|
|
21
|
+
data_str = data_str[9:]
|
|
22
|
+
if len(data_str) != 32:
|
|
23
|
+
raise OpenSslError("error reading md5 (ii)")
|
|
24
|
+
return data_str
|