Skip to main content

x509kit

tests python license deps

Pure-Python X.509 / PKCS#10 / CRL / OCSP / PKCS#12 toolkit. Standard library only.

No third-party packages. No C extensions. No vendored code.

Zero third-party dependencies

x509kit uses only the Python standard library. No cryptography, no pyOpenSSL, no asn1crypto, no pycryptodome, no C extensions.

$ pip show x509kit | grep "^Requires"
Requires:

$ grep -rhE "^\s*(import|from) " src/x509kit/ \
    | awk '{print $2}' | cut -d. -f1 | sort -u
base64
datetime
hashlib
hmac
math
os
re
secrets
socket
unicodedata
warnings

All of these are in the Python standard library. Nothing else.

Why stdlib only

  • No transitive CVEs. Fewer packages — fewer places for something to go wrong.
  • Embedded / restricted environments where you cannot install third-party packages.
  • Air-gapped systems — drop a single package and run.
  • Readable. The whole implementation is in one place.
  • Auditable. The attack surface is exactly one package.

What is implemented from scratch

Every protocol and primitive is our own Python code:

  • ASN.1 DER parser and encoder (strict, minimal-length)
  • RSA PKCS#1 v1.5 and RSASSA-PSS (with blinding and CRT)
  • Ed25519 (RFC 8032)
  • ECDSA (RFC 6979 deterministic nonces)
  • AES-256 block cipher (FIPS 197) and GCM mode (NIST SP 800-38D)
  • PBKDF2 and PKCS#12 KDF
  • Every X.509 v3, PKCS#10, PKCS#12, CRL, OCSP structure
  • RFC 4518 DN canonicalization

Hashing (hashlib), MAC (hmac), and randomness (secrets) come from the standard library — writing a custom SHA-256 in Python would be slower and less tested than what the interpreter already ships.

cryptography and the openssl binary appear only in tests, as independent verifiers of our output.

Verify it is really stdlib-only

Do not grep for the word "cryptography" — it appears in documentation comments saying "we do not use it". Instead, run this:

python check_no_hidden.py

This script uses Python's ast module to extract every import statement from every .py file under src/. It compares the result against sys.stdlib_module_names and a small blacklist of crypto libraries.

Expected output ends with:

RESULT: OK - stdlib only

If it prints anything else, that is a bug — please open an issue.

Verify in 30 seconds

Not asking you to trust me — asking you to run this:

git clone https://github.com/artem122py/x509kit
cd x509kit
pip install -e .
python flask/test_live_ca.py

In one go, this script:

  • Generates Root CA + Intermediate in memory (nothing on disk)
  • Issues a server leaf certificate for a Flask server
  • Starts Flask on HTTPS with the leaf + intermediate chain
  • Calls the real OpenSSL CLI to generate a key and a CSR
  • POSTs the CSR to the server, gets a leaf back
  • Runs openssl verify -CAfile root -untrusted inter leaf.pem → expected output: leaf.pem: OK
  • Revokes the leaf via /revoke
  • Runs openssl verify -CRLfile crl.pem -crl_check → expected output: error 23 at 0 depth lookup: certificate revoked

The verification step is done by OpenSSL 3.x, called via subprocess. It is not our own verify() method. If our DER encoding were wrong, OpenSSL would reject it — and it doesn't.

Cross-verify matrix

The library is not self-tested. It is tested against external implementations, in both directions:

Component Independent verifier Result
RSA (PKCS#1 v1.5, PSS) cryptography + openssl pkeyutl both ways
Ed25519 RFC 8032 test vectors (byte-exact), cryptography both ways
ECDSA (P-256/384/521/secp256k1) RFC 6979 test vectors (byte-exact), cryptography both ways
AES-256-CBC FIPS 197 test vector byte-exact
AES-256-GCM NIST SP 800-38D test vectors byte-exact
X.509 v3 certificates openssl x509 -text, openssl verify OK
Chains (root → intermediate → leaf) Python ssl TLS handshake OK
CRL openssl crl -text, openssl verify -crl_check error 23
PKCS#12 (.p12) openssl pkcs12 -info -nodes 3 blocks extracted
PKCS#8 EncryptedPrivateKeyInfo openssl pkey OK
mTLS openssl s_client -cert -key handshake OK

Run it yourself:

python test_all.py

Compatibility with cryptography

Run this yourself — it verifies that x509kit and cryptography agree in both directions, for every primitive:

python compat_test.py

Expected output:

============================================================
  x509kit ↔ cryptography
============================================================

1. RSA PKCS#1 v1.5
  ✓ наш RSA sign → их verify
  ✓ их RSA sign → наш verify

2. Ed25519 (RFC 8032)
  ✓ seed → тот же pubkey
  ✓ наш Ed sign → их verify
  ✓ их Ed sign → наш verify

3. ECDSA P-256
  ✓ наш EC sign → их verify
  ✓ их EC sign → наш verify

4. X.509 сертификат
  ✓ наш PEM → их x509 парсер
  ✓ серийник совпадает
  ✓ их PEM → наш Cert парсер

5. Полная цепочка
  ✓ их SAN читает наш leaf
  ✓ их CA парсится нашим CACert

============================================================
  12/12 passed
============================================================

This is not a self-test. Every check calls into cryptography (which links against OpenSSL) and asks it to verify our output, or vice versa. If any row fails, our implementation is wrong.

Requires: pip install cryptography

Examples

See examples/ — 12 runnable scripts covering the whole library:

  • 01_root_ca.py — self-signed CA
  • 02_issue_from_csr.py — issue leaf from CSR
  • 03_self_signed_server.py — HTTPS with self-signed cert
  • 04_mtls_server.py — mutual TLS
  • 05_crl_revocation.py — revoke and generate CRL
  • 06_ocsp_responder.py — OCSP response
  • 07_pkcs12_export.py — export to .p12
  • 08_parse_real_cert.py — fetch and parse a live HTTPS cert
  • 09_encrypted_key.py — encrypted PKCS#8 keys
  • 10_verify_chain.py — chain verification scenarios
  • 11_name_canonicalization.py — RFC 4518
  • 12_extensions.py — all extensions in one cert

Each is self-contained, prints what it does, and shows the OpenSSL command to verify the result.

What this is

A learning project that turned into a working implementation. It exists to answer the question: what actually happens inside an X.509 certificate — by writing it from scratch, on the standard library, and checking the result against OpenSSL until they agree.

What this is not

Not a replacement for OpenSSL or cryptography in production. See SECURITY.md for the full list of what is covered and what is not. Short version: no constant-time guarantees, no formal audit, no production hardening.

If you need production-grade crypto: use cryptography. If you want to understand X.509 by reading Python that OpenSSL agrees with: this is for you.

Install

pip install x509kit

Quick example

from x509kit import CertificateBuilder, Ed25519Keys, RSAKeys

ca_key = Ed25519Keys.generate()
ca = (CertificateBuilder(is_ca=True)
    .add_subject({"C": "XX", "O": "MyOrg", "CN": "MyOrg Root CA"})
    .add_public_key(ca_key)
    .add_serial_random().add_validity(days=3650)
    .add_basic_constraints(path_len=0)
    .add_key_usage("keyCertSign", "cRLSign")
    .self_signed().sign(ca_key))

leaf_key = RSAKeys.generate(2048)
leaf = (CertificateBuilder()
    .add_subject({"C": "XX", "O": "MyOrg", "CN": "example.com"})
    .add_issuer(ca).add_public_key(leaf_key)
    .add_serial_random().add_validity(days=365)
    .add_san_dns("example.com", "www.example.com")
    .add_extended_key_usage("serverAuth")
    .sign(ca_key))

assert ca.verify_chain([leaf])

Features

  • ASN.1 DER parser and encoder (strict, minimal-length)
  • PEM codec
  • RSA PKCS#1 v1.5 + RSASSA-PSS (blinding + CRT)
  • Ed25519 (RFC 8032), ECDSA (P-256/384/521/secp256k1, RFC 6979)
  • X.509 v3: SAN, BasicConstraints, KeyUsage, Extended Key Usage, Name Constraints (with intersection), AKI/SKI, CRL Distribution Points, AIA
  • PKCS#10 CSR, CRL (RFC 5280), OCSP (RFC 6960), PKCS#12 (RFC 7292)
  • PKCS#8 EncryptedPrivateKeyInfo (PBES2 + PBKDF2 + AES-256-CBC/GCM)
  • RFC 4518 DN canonicalization
  • Fluent builders: CertificateBuilder, CSRBuilder, CRLBuilder, OCSPResponseBuilder, PKCS12Builder
  • X509Error with fix hints, X509Warning for non-fatal issues

Status

Alpha (0.3.0). Educational. Not for production. See SECURITY.md.

License

MIT

Metadata

Release files for x509kit 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for x509kit 0.3.2
File Size Uploaded
x509kit-0.3.2.tar.gz 110.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for x509kit 0.3.2
File Interpreter ABI Platform
x509kit-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 180.1 kB

Release files / x509kit-0.3.2.tar.gz

Download URL x509kit-0.3.2.tar.gz
Size 110.7 kB
Tags Source
SHA-256 checksum
How to use checksums
90bbb271eda4c611e771be1cd2cf1790791aa217eb5a3d80ec872a90bf45b81a
BLAKE2b-256 checksum
How to use checksums
cedbf7316062ac2f46ad99acf4f93571ce0a41840a4b314d9cdcbec592c55f0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / x509kit-0.3.2-py3-none-any.whl

Download URL x509kit-0.3.2-py3-none-any.whl
Size 69.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ab464b886422aa6e9fe326d0cb953669e766c8d176321bc78f09f580413fbbbd
BLAKE2b-256 checksum
How to use checksums
d9f4002e10bdc5fdcc5b70e5601be12caee469a41381af8f9e0d39d94141b08f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release history Release notifications | RSS feed

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

This release

0.3.2 This release

2 release files

0.3.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page