Six government passport CAs that Python rejects and OpenSSL accepts
Eginn-33
14 points
2 comments
August 26, 2026
Related Discussions
Found 5 related stories in 87.7ms across 9,063 title embeddings via pgvector HNSW
- I've factored the RSA keys of a Certificate Authority from the 90s ahlCVA · 232 pts · September 08, 2026 · 45% similar
- RSA-896 madars · 90 pts · September 20, 2026 · 43% similar
- Keys Not Included: recovering the signing keys for US driver's license barcodes Ryan5453 · 97 pts · September 17, 2026 · 42% similar
- The State of MCP Security [pdf] mavzer · 26 pts · July 12, 2026 · 42% similar
- Six curl CVEs after OpenAI and Anthropic came back with zero goobreee · 163 pts · September 02, 2026 · 41% similar
Discussion Highlights (1 comments)
Eginn-33
Author here. Some background on why this exists. To validate the signature on an electronic passport you need the issuing country's CSCA certificate. States distribute these in bulk as a "Master List" - a CMS SignedData wrapping a SEQUENCE OF Certificate, specified in ICAO Doc 9303 Part 12. The format is not hard. What surprised me is how little public tooling just opens the file and hands you the certificates; most eMRTD code buries the parse inside a larger verification stack. So I wrote the parse on its own. Then I ran it against a real Master List and six of the 581 entries failed: ParseError { kind: ExtraData, location: ["Certificate::tbs_cert", "TbsCertificate::signature_alg"] } They are not junk. OpenSSL reads every one of them: C=AT, O=GV, OU=BMI, CN=CSCA-AUSTRIA (x2) C=AE, O=MOI, OU=EPASS, CN=UAE CSCA 02 (x1) C=JP, O=Japanese Government, OU=MOFA, CN=e-passportCSCA (x3) Live, government-issued CAs carrying trailing bytes in the signature AlgorithmIdentifier that the Rust ASN.1 parser in `cryptography` treats as ExtraData. Austria, the UAE and Japan are not edge cases you get to skip: drop them silently and passports from those states fail with "unknown issuer" instead of a real error - which is genuinely unpleasant to debug, because the trust store looks fine and the count looks plausible. So the default path falls back to `openssl x509` for anything the strict parser refuses, and the manifest records which parser produced each row, so the gap is visible rather than silent. --strict turns the fallback off if you want to see what a strict parser alone gives you. It handles only public trust anchors - the certificates states publish precisely so that anyone can validate the documents they issue. No private keys, no chip communication, no passport data. I have not torn those six apart byte by byte yet; my guess is a redundant explicit NULL or a PSS parameter block. Would be glad to hear from anyone who has hit the same six, or a different set from a newer Master List.