Six government passport CAs that Python rejects and OpenSSL accepts A new open-source tool, extract_masterlist.py, parses ICAO/BSI CSCA Master Lists and exports country signing CA certificates as PEM bundles or TSV manifests, handling 581 entries across 112 countries in a test run. The tool defaults to an OpenSSL fallback because six live government-issued certificates from Austria, the UAE, and Japan fail strict DER parsing in Python's cryptography library due to trailing bytes in the signature AlgorithmIdentifier, and silently dropping them would cause passport validation failures. The project is available on GitHub and requires only the cryptography package, with OpenSSL optional for lenient parsing. Parse an ICAO / BSI CSCA Master List .ml and export every Country Signing CA certificate inside it — as a PEM bundle, as a TSV manifest, or just as a count. One file, one dependency, no framework. python extract masterlist.py DE ML 2026-01-08.ml -o csca bundle.pem -m manifest.tsv master list : DE ML 2026-01-08.ml 891,227 bytes entries : 581 parsed : 581 openssl fallback rescued 6 unparsable : 0 unique : 581 countries : 112 top issuers : CN=26, HU=21, BE=19, LU=12, TR=12, LV=11, AU=10, GR=10, MT=10, NL=10 PEM bundle - csca bundle.pem manifest - manifest.tsv A Master List is the trust anchor set for electronic passports: to validate the SOD on any eMRTD you need the issuing country's CSCA, and Master Lists are how states distribute them in bulk. The format is specified in ICAO Doc 9303 Part 12 and BSI TR-03129 : ContentInfo └─ SignedData └─ encapContentInfo.eContent OCTET STRING └─ CscaMasterList ::= SEQUENCE { version INTEGER, certList SET OF Certificate } That is not hard — but there is remarkably little public tooling that just opens the file and gives you the certificates . Most eMRTD code buries the parse inside a larger verification stack. This repo is the parse on its own. Run against a real Master List with --strict and six entries drop on the floor: entries : 581 parsed : 575 unparsable : 6 All six fail inside cryptography 's Rust ASN.1 parser with: ParseError { kind: ExtraData, location: "Certificate::tbs cert", "TbsCertificate::signature alg" } They are not junk. OpenSSL reads every one of them: | | Subject | |---|---| | 48, 49 | C=AT, O=GV, OU=BMI, CN=CSCA-AUSTRIA | | 61 | C=AE, O=MOI, OU=EPASS, CN=UAE CSCA 02 | | 84, 85, 90 | C=JP, O=Japanese Government, OU=The Ministry of Foreign Affairs, CN=e-passportCSCA | These are live, government-issued CSCAs carrying trailing bytes in the signature AlgorithmIdentifier that a strict DER parser rejects. Austria, the UAE and Japan are not edge cases you get to skip — silently dropping them means passports from those countries fail validation with a confusing "unknown issuer" instead of a real error. So the default path falls back to openssl x509 for anything cryptography refuses, and the manifest records which parser produced each row: country subject ... parser AT CN=CSCA-AUSTRIA,OU=BMI,... ... openssl AD CN=CSCA-AND,OU=MJI,... ... cryptography Use --strict if you want the lenient path off and the failures visible. pip install -r requirements.txt cryptography openssl on PATH is optional; without it, --strict behaviour is the only behaviour and the six certificates above are reported as unparsable. extract masterlist.py MASTERLIST -o BUNDLE.pem -m MANIFEST.tsv --keep-duplicates --strict | flag | effect | |---|---| -o , --out | write the concatenated PEM trust bundle | -m , --manifest | write a TSV row per certificate country, subject, serial, validity, sig alg, SHA-256, size, parser | --keep-duplicates | keep every entry; default de-duplicates by SHA-256 | --strict | no OpenSSL fallback | With no output flags it prints statistics and exits — useful for diffing two Master List releases. See examples/manifest sample.tsv /Eginn-33/csca-masterlist-tools/blob/main/examples/manifest sample.tsv for the manifest shape. ICAO PKD — https://pkddownloadsg.icao.int/ https://pkddownloadsg.icao.int/ the authoritative source German BSI — publishes a national Master List that aggregates a large share of participating states No Master List is bundled here, and .gitignore refuses to commit one. Fetch your own and keep it fresh: CSCAs roll over, and a stale trust store is how you end up rejecting valid documents. JMRTD https://jmrtd.org/ — the long-running open-source eMRTD implementation Java . Also publishes per-country CSCA certificates, useful when you want a handful of anchors rather than a whole Master List. Kinegram eMRTD Connector https://github.com/OVD-Kinegram-AG/emrtd-connector-sdk-ios — open-source client for a commercial chip-verification service. Neither of them will hand you the certificates out of a .ml file, which is what this repo is for. This tool reads public trust anchors — the certificates states publish specifically so that anyone can validate the passports they issue. It handles no private keys, no chip communication, and no passport data. It is the boring, public half of eMRTD work, which is exactly why it can be open. MIT