cd /news/developer-tools/six-government-passport-cas-that-pyt… Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-112278] src=github.com β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

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.

read3 min views2 publishedAug 26, 2026
Six government passport CAs that Python rejects and OpenSSL accepts
Image: Michielbdejong (auto-discovered)

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 for the manifest shape.

ICAO PKDβ€”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β€” 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β€” 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

── more in #developer-tools 4 stories Β· sorted by recency
── more on @extract_masterlist.py 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/six-government-passp…] indexed:0 read:3min 2026-08-26 Β· β€”