Skip to content

How to contribute CSCA/DSC coverage for additional countries (IL, PT)? #1962

Description

@dagangilat

Hi Self team — I'm building a proof-of-humanity layer for Foundation, a governance platform on Solana, and Self is our high-trust ePassport path. First, thanks for the work — the SDK integration was straightforward and Phase 1 of our rollout is live on devnet.

Per your contribution guidelines, opening this issue before starting work. I'd like to contribute country coverage for Israel and Portugal and want to check with you on the right workflow before doing the work.

What I observed

Parsing common/pubkeys/public_keys_parsed.json at HEAD:

  • IL: 0 entries (substring search for "Israel" also zero)
  • PT: 0 entries (substring search for "Portugal" / "Portuguesa" also zero)
  • By comparison: FR 2048, GB 2047, US 1458, ES 167

Live scans confirm the registry state: a current Israeli biometric national ID and a Portuguese Cartão de Cidadão (ePassport) both fail verification in the Self mobile app — neither document produces a successful proof. Both countries are ICAO PKD participants, so CSCA/DSC material is publicly available.

What I'm unsure about

  1. Is public_keys_parsed.json still the right place to contribute? The file was last updated 2024-12-02, and I understand the on-chain Identity Registry on Celo is the authoritative trust anchor circuits verify against. If a PR to the JSON file no longer changes runtime behavior, what's the correct path — a registry update via contracts/scripts/setRegistry.ts, coordination with the team for a batch update, or something else?

  2. Signature algorithm compatibility. Before I prepare IL/PT DSC material, is there a documented list of signature algorithms / curve parameters currently supported by the circuits? I want to avoid submitting keys that would require circuit changes to verify.

  3. Preferred source format. Do you prefer raw PKD master list extracts, pre-parsed JSON in the existing schema, or something else?

Happy to do the work — just want to make sure it lands somewhere useful. A Discord channel or different repo for this kind of contribution would also work if GitHub isn't the right venue.

Thanks!

— Dagan Gilat, Founder @ Foundation

Activity

  1. Nesopie commented on Apr 13, 2026

    @Nesopie
    Collaborator

    Hi @dagangilat thanks for the issue! You're correct that we currently don't rely on common/pubkeys/public_keys_parsed.json We're currently working on our CSCA pipeline to make it more transparent for our users so it would be great if there's a legitimate source / public link for the CSCAs you have. TIA!

    Edit: You can find the supported signature algorithms here

  2. dagangilat commented on Apr 14, 2026

    @dagangilat
    Author

    Thanks @Nesopie for the quick response and the pointer to the circuit file!

    I checked the supported algorithms — both countries use standard RSA-SHA256, which maps to existing circuit IDs:

    Country CSCA Algorithm Circuit ID
    Israel RSA-4096 / SHA-256 / e=65537 10 (rsa_sha256_65537_4096)
    Portugal RSA-3072 or 4096 / SHA-256 14 or 10

    So no circuit changes needed — just the CSCA certificates.

    Sources I've found

    Important discovery: Neither Israel nor Portugal is an ICAO PKD participant (participants list), so their CSCAs aren't in the ICAO master list.

    Best bet — German BSI Master List
    The BSI publishes a compiled CSCA master list covering 114 countries via bilateral exchange (more than the PKD's 109). It's freely downloadable:

    I haven't confirmed IL/PT are in there yet — tools like nicocha/CSCA-masterlist or ciarancarolan/eMRTD-PKD can parse the .ml file to extract individual PEM certs per country. Happy to do this and submit the extracted certs if that's helpful.

    Portugal — direct government source
    Portugal's IRN (Instituto dos Registos e do Notariado) publishes their CSCA directly:

    Israel
    No public government CSCA page exists. The BSI master list (bilateral exchange) is likely the only public path. If it's not there, I have physical access to a current Israeli biometric ID and can extract the CSCA from the SOD via NFC if that would help as a starting point for cross-verification.

    Other references

    A few other projects maintaining CSCA registries that might be useful for your pipeline:

    Next steps from my side

    1. Download and parse the BSI master list to confirm IL/PT presence
    2. If present, extract the PEM certs and share them here
    3. If not, extract Portugal's from the IRN source and Israel's from a physical document via NFC
  3. dagangilat commented on Apr 14, 2026

    @dagangilat
    Author

    Update: CSCA certificates extracted and verified

    I downloaded and parsed the German BSI CSCA Master List (issued 2026-01-08, 581 certificates, 116 countries). Both Israel and Portugal are present despite not being ICAO PKD participants — Germany obtained them via bilateral exchange.

    Source: BSI Master List ZIP (493KB, freely downloadable)

    Extracted PEM files: https://gist.github.com/dagangilat/2a3447ed370b9e6d251f39678f48698b


    Extraction method

    The .ml file is CMS-signed. Extract and parse with:

    # 1. Extract CMS content
    openssl cms -inform DER -in DE_ML_2026-01-08-12-20-54.ml -verify -noverify -out ml_content.der
    
    # 2. Parse ASN.1 structure (SET of 581 X.509 certs)
    openssl asn1parse -inform DER -in ml_content.der

    Then iterate over all d=2 SEQUENCE entries, extract each as DER, parse with openssl x509, and filter by country code.

    Full Python extraction script
    import subprocess, re, os
    
    with open('ml_content.der', 'rb') as f:
        data = f.read()
    
    r = subprocess.run(
        ['openssl', 'asn1parse', '-inform', 'DER', '-in', 'ml_content.der'],
        capture_output=True, text=True
    )
    
    certs = []
    for line in r.stdout.split('\n'):
        m = re.match(r'\s*(\d+):d=2\s+hl=(\d+)\s+l=\s*(\d+)\s+cons:\s*SEQUENCE', line)
        if m:
            certs.append((int(m.group(1)), int(m.group(2)), int(m.group(3))))
    
    for cc in ['IL', 'PT']:
        os.makedirs(f'csca_certs/{cc}', exist_ok=True)
    
    count = {'IL': 0, 'PT': 0}
    for offset, hl, length in certs:
        cert_der = data[offset:offset+hl+length]
        with open('tmp.der', 'wb') as f:
            f.write(cert_der)
        r2 = subprocess.run(
            ['openssl', 'x509', '-inform', 'DER', '-in', 'tmp.der', '-noout', '-subject'],
            capture_output=True, text=True
        )
        if r2.returncode != 0:
            continue
        subject = r2.stdout.strip()
        for cc in ['IL', 'PT']:
            if re.search(rf'\bC\s*=\s*{cc}\b', subject):
                count[cc] += 1
                pem = subprocess.run(
                    ['openssl', 'x509', '-inform', 'DER', '-in', 'tmp.der', '-outform', 'PEM'],
                    capture_output=True, text=True
                )
                with open(f'csca_certs/{cc}/{cc}_csca_{count[cc]:02d}.pem', 'w') as f:
                    f.write(pem.stdout)
                print(f'{cc}_csca_{count[cc]:02d}.pem — {subject}')
                break
    os.remove('tmp.der')

    Israel — 5 CSCA certificates (Issuer: PIBA)

    # CN Algorithm Key Valid
    1 EPPCSCA ecdsa-with-SHA384 384-bit secp384r1 2023-07 → 2039-01
    2 EPPCSCA rsassaPss 384-bit 2023-07 → 2039-01
    3 EPPCSCA sha256WithRSA 4096-bit 2018-08 → 2034-02
    4 EPPCSCA rsassaPss 4096-bit 2013-05 → 2028-11
    5 EPPCSCA rsassaPss 4096-bit 2018-08 → 2034-02

    Portugal — 6 CSCA certificates (Republica Portuguesa — ICAO MRTD PKI)

    # CN Algorithm Key Valid
    1 ECN Documentos de Viagem 006 sha256WithRSA 4096-bit 2019-06 → 2027-11
    2 ENC 006 007 (crosslink) sha256WithRSA 4096-bit 2022-06 → 2027-11
    3 ECN Crosslink 007-008 sha512WithRSA 4096-bit 2023-10 → 2030-08
    4 ECN Crosslink 007-008 sha512WithRSA 4096-bit 2024-03 → 2030-08
    5 ECN Documentos de Viagem 008 sha512WithRSA 4096-bit 2023-10 → 2037-01
    6 ECN Documentos de Viagem 007 sha512WithRSA 4096-bit 2022-06 → 2030-08

    Algorithm compatibility with Self circuits

    Cross-referenced against signatureAlgorithm.circom:

    Algorithm Circuit ID Status
    RSA-SHA256 / 4096 / e=65537 10 Supported
    RSA-SHA512 / 4096 / e=65537 15 Supported
    RSA-PSS SHA256 / 4096 12 Supported
    ECDSA-SHA384 / secp384r1 9 Supported

    All algorithms are already covered by existing circuits. No circuit changes needed.

    Let me know what else you need from my side — happy to open a PR if there's a target directory for these.

  4. Nesopie commented on Apr 14, 2026

    @Nesopie
    Collaborator

    Hi @dagangilat, thank you for this! We already parse the German / Netherlands masterlist and after de duplicating by SKI we have 3 certs for Israel and Portugal

  5. Nesopie commented on Apr 14, 2026

    @Nesopie
    Collaborator

    Adding on to this, we already have these certs in our current tree. Can you tell us what exactly was failing / the error message you received when you created the proof? Thanks!

  6. dagangilat commented on Apr 16, 2026

    @dagangilat
    Author

    Hi @Nesopie, thanks for looking into this!
    Good news — I retested today and both Israeli biometric passport and Portuguese biometric passport verify successfully in the Self app. Full ZK proofs generated, both show as HI-SECURITY. So the passport path is working for IL and PT.

    What does fail is ID cards — specifically the Israeli biometric national ID card (Teudat Zehut) and the Portuguese Cartão de Cidadão. Here's the exact flow for the Israeli ID card case:

    1. Select Israel → select "ID card" type
    2. App asks to scan an MRZ line, but the Israeli ID card doesn't have a standard passport-style MRZ
    3. To get past that step, I pointed the camera at my Israeli passport's MRZ instead — MRZ read succeeded
    4. Then held the ID card to the NFC reader for the chip scan
    5. Failed with: "There was a problem reading the chip" — presumably because the MRZ data (from the passport) doesn't match the chip data on the ID card

    The Portuguese Cartão de Cidadão had the same issue — no compatible MRZ on the card to scan.

    Summary of 4 documents tested:

    Document Result
    Israeli Passport ✅ SUCCESS — full ZK proof, HI-SECURITY
    Portuguese Passport ✅ SUCCESS — full ZK proof, HI-SECURITY
    Israeli ID Card (Teudat Zehut) ❌ FAIL — MRZ/chip mismatch, NFC read fails
    Portuguese Cartão de Cidadão ❌ FAIL — same issue, no compatible MRZ on card

    Device: iPhone 13 (MLPK3HB/A), iOS 26.4.1, latest Self app version. Happy to test further or provide additional details. Thanks again for the quick responses!

  7. Nesopie commented on Apr 16, 2026

    @Nesopie
    Collaborator

    Hi! Can you confirm that the MRZ on the Israeli and Portugese ID Cards has 3 lines? This seems like an NFC reading issue. Tagging @seshanthS, for the NFC issue

  8. dagangilat commented on Apr 16, 2026

    @dagangilat
    Author

    Hi @Nesopie,

    Thanks for looking into this!
    Here's a full update after retesting all four documents.

    Passports — both working:
    Both the Israeli and Portuguese biometric passports now verify successfully with full ZK proofs (HI-SECURITY). The passport path is fully working for IL and PT.

    ID cards — MRZ scan fails, but alternative method works:

    1. Israeli Biometric ID Card (Teudat Zehut): The app prompts to "Align the animation with the MRZ on the passport," but the Israeli biometric ID card has no MRZ lines at all. There is no way to proceed past this step. (The Israeli biometric passport has 2 MRZ lines and verifies successfully.)

    2. Portuguese Cartão de Cidadão: Same prompt — "Align the animation with the MRZ on the passport." The Portuguese biometric ID card does have 3 MRZ lines (TD1 format), but the app doesn't recognize them. (The Portuguese biometric passport has 2 MRZ lines in TD3 format and verifies successfully.)

    3. Workaround — "Try a different method": After the NFC scan failure, I used the "Try a different method" button and was able to successfully add and verify both the Israeli biometric ID card and the Portuguese Cartão de Cidadão.

    The core issue seems to be that the MRZ scanner only supports the 2-line TD3 (passport) format and doesn't handle TD1 (ID card) format — or in the Israeli case, the complete absence of an MRZ. The alternative verification method does work for both cards.

    Device: iPhone 13, iOS 26.4.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions