Skip to content

Only issue credentials based on verified chip data #85

Open

Description

@s-jairl

Summary

Restrict credential issuance and claim inclusion to data that has been cryptographically verified for authenticity.

Background

This is issue stems from a discussion in #84 regarding how data is read/validate for issuance:

FaceTec has to report an authenticated chip for every issuance, but we can still issue OCR values in three cases:

  • a chip FaceTec authenticates but our own passive authentication can’t verify (only enforced as a refusal for passports with trust.required);
  • chips we don’t parse, e.g. ISO 18013 driving licences;
  • the legacy /v1/id-scan path.
    Requiring chip-signed identity for every credential would close these, but would also exclude driving licences until we support ISO 18013 chips. That’s a team decision, so I’ll keep it out of this PR.

Problem description

Claim data read via OCR from an identity document is trivial to falsify. It is also trivial to fraudulently apply cryptographic signatures over forged data unless the validator has a list of trusted signers (typically through PKI). It would hence be a great liability to issue credentials based on this.

Suggested solution

Never use data that hasn't been cryptographically verified against a trust list in issued credentials.

Considerations

As stated in other discussions, this type of change would prevent usage of certain identity documents from certain countries. While that is a downside, I would argue that we can't let these cases compromise the trust in our validation process for issued credentials.

Activity

  1. leifj commented on Oct 14, 2026

    @leifj
    Contributor

    I agree. This is what the emrtd-anchors repo is for basically.

  2. s-jairl commented on Oct 14, 2026

    @s-jairl
    ContributorAuthor
    1. I agree. This is what the emrtd-anchors repo is for basically.

    I believe that is used in cases where possible - this issue is more about a stance and guiding principles for the project.

  3. jessevanmuijden commented on Oct 14, 2026

    @jessevanmuijden
    Contributor

    Agreed. Here is a concrete implementation plan, for confirming the scope before I build it.

    "Verified against a trust list" means the go-trust PDP trusts the document signer (chip-trusted, emrtd-anchors). A valid chip signature on its own is not enough, since anyone can sign forged data with their own key.

    Plan

    1. Trust required for every document type. trust.required is enforced for passports only today (assessChip). Extend it to all documents, so ID cards also need a document signer that chains to a CSCA in emrtd-anchors. ID cards are ICAO 9303 documents too, and many states sign them under the same CSCA as their passports.
    2. No OCR identity in a credential. Add a hard gate that refuses issuance unless the identity was taken from the verified, trusted chip. This builds on fix: take the identity claims from the chip, not from MRZ OCR #84.
      • Names, dates, document number, nationality and sex then always come from DG1/DG11.
      • The age claims are derived from that date of birth.
      • The portrait already comes from DG2 only for a trusted chip.
      • OCR is still used for the document type, which must match the chip's signed document code, and for mismatch diagnostics. Nothing OCR'd reaches the credential.
    3. Legacy /v1/id-scan. It never receives chip data, so under this rule it can only refuse. I would remove /v1/session-token, /v1/liveness and /v1/id-scan, or have them always refuse. No working client uses them: the SDKs' FaceTec 9 delegate cannot run against FaceTec 10.
    4. Driving licences. They are refused until ISO 18013 chips are supported, which needs their own parser and trust lists (licence issuers, not passport CSCAs). As noted above, this is the accepted cost.

    To settle

    • Coverage. The states in emrtd-anchors decide who can get a Photo ID. Documents from missing states are refused (chip_untrusted), ID cards included. Worth checking that list against the states we expect users from.
    • Dev/test. Keep trust.required: false as an explicit opt-out for development stacks without a PDP, with a startup warning, and keep it true in production. Is that acceptable, or should production builds refuse the opt-out entirely?
    • Refusal code. Is a new code for the identity gate (e.g. chip_data_unverified) wanted, or should it reuse chip_untrusted? A new code also means a message in the apps and SDKs.

    Order

    #84 (identity from the chip) is a prerequisite and #80 (chip photo match) follows the same principle, so I would merge both first and then do this as its own PR.

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