A QR code cannot prove anything by itself: anyone can print one. What it can do is carry a small signed document, or a pointer to one, that a verifier can check against the issuer’s public key. That idea, a credential in a code, took off with boarding passes, was tested on the whole world during the pandemic, and is about to become the way Europeans show their ID. This article follows it through those stages.
The pattern
There are two ways to put identity in a code, and both are in use.
The credential is in the code. The QR code contains the signed data itself: name, date of birth, a photo hash, whatever the credential asserts, plus the issuer’s signature. The verifier reads it offline and checks the signature. A boarding pass works this way, as did pandemic health certificates. The limit is size: a QR code holds under 3 KB, so credentials are compressed and photos are left out.
The code is a handshake. The QR code contains a one-time link or session identifier. The verifier’s screen shows it, you scan it with your wallet app, and the two devices set up a secure channel through which the wallet sends only the fields the verifier asked for. This is how the EU wallet works in a shop or at a desk, and how “log in by scanning” works on a website. The code itself contains nothing about you, which is why it is safe to display on a public screen and why the QRLjacking attack targets the scanning step rather than the code.
Both build on the idea of a verifiable credential: in the W3C’s definition, “a tamper-evident credential whose authorship can be cryptographically verified” (W3C Recommendation, 15 May 2025).
Boarding passes
The oldest mass use of a credential in a 2D code is the airline boarding pass. IATA’s Bar Coded Boarding Pass standard, Resolution 792, fixes both the data layout and the symbologies allowed: PDF417 for printed passes, and Aztec, QR code or Data Matrix for passes shown on a phone (IATA implementation guide). Every compliant pass encodes the same fields in the same order: passenger name, booking reference, flight, date, seat and security data, so any gate reader in the world can parse any airline’s pass.
Aztec became the phone favourite because it has no quiet zone requirement and a central bullseye that reads well from a bright screen (Wikipedia). The other 2D codes article compares the three.
| Feature | Boarding pass (BCBP) | SMART Health Card | EUDI Wallet | App Clip Code |
|---|---|---|---|---|
| Symbology | PDF417, Aztec, QR, Data Matrix | QR (numeric mode) | QR | Apple proprietary |
| What the code holds | The credential itself | The signed credential itself | A session handshake or the credential | A URL |
| Signed by issuer | Optional (security field) | ✓ | ✓ | ✕ |
| Works offline | ✓ | ✓ | Proximity mode yes | ✕ |
| Standard body | IATA | VCI / HL7 community | EU Regulation 2024/1183 | Apple |
SMART Health Cards: the pandemic test
During 2021 hundreds of millions of people carried a vaccination record in a QR code. In the United States, Canada and elsewhere the format was the SMART Health Card, an open specification written by a coalition of health IT vendors and labs. It is a good case study because it shows what fitting a signed record into a code takes.
The credential is a JSON Web Signature. To fit it in a QR code, the specification prefixes it with shc:/ and converts every character to two digits, each character’s code minus 45, so that the whole thing can use the QR code’s numeric mode, which packs three digits into ten bits (SMART Health Cards specification). The result is a code of roughly version 22 that decodes offline into a signed record a verifier app can check.
Raw payload
shc:/5676290952432060346029243740446031222959532654603460292540772804336028702864716745222809286133314564376531415906402203064504590856435503414245413640370636654171372412363803043756220467374075323239254334433260573601064529315312707424284350386122127671665437 -
shc:/Scheme prefix registered with IANA, so a reader knows what follows. -
56762909524320603460Pairs of digits. 56 stands for the character with code 56 plus 45, which is e; the JWS begins eyJ. Encoded in numeric mode to save space.
The specification is still maintained at version 1.4.0 (SMART Health Cards), but with pandemic checks ended it is now mainly history. Its lesson carried forward: put a real signature in the code, keep the record small, and decode offline.
The EU Digital Identity Wallet
Regulation (EU) 2024/1183, in force since 20 May 2024, requires every member state to offer at least one European Digital Identity Wallet, free to citizens, by 24 December 2026. From 24 December 2027 businesses and public bodies in listed sectors must accept it (Intesa, Wikipedia). The wallet holds a person’s identity data plus attestations such as a driving licence, a diploma or a proof of age.
QR codes are the wallet’s way of presenting a credential when two devices are in the same room. The verifier shows a code, or the wallet does; the other side scans it; the devices connect over Bluetooth or the internet and the wallet sends only the requested attributes. Age verification at a shop can send “over 18: yes” and nothing else. The Commission’s reference implementation and the Architecture and Reference Framework are published openly on GitHub.
Three things to expect in 2027:
- Codes on shop counters and kiosks that begin a wallet session, replacing “show me your card”.
- Codes on websites for logging in or proving age from a phone, the handshake pattern.
- A wave of fake codes imitating the real ones, because the wallet’s own security will make the surrounding social engineering the weak point. The security article applies here in full.
App Clip Codes
Apple’s App Clip Code is a different kind of identity: the identity of a place or an object rather than a person. It is a round, Apple-designed code that encodes a URL and optionally includes an NFC tag, so an iPhone can either scan it with the camera or be held against it. Scanning launches an App Clip, a small slice of an app, without installing the app. Apple shipped support in iOS 14.3 in December 2020 and provides a command-line generator, AppClipCodeGenerator, in Xcode (NFCW, Apple Developer). Only iPhones read it, which is why most deployments print an ordinary QR code beside it.
In practice
Whenever a code stands for a person, print nothing sensitive in it that a photograph could steal. A boarding pass barcode contains your booking reference, which is enough to change your flight. Do not post a photo of it.
▸Why the wallet prefers a handshake to a credential in the code
A credential in a code is fixed once printed or displayed: it reveals every field it contains to anyone who scans it, and a screenshot of it works as well as the original. A handshake code carries nothing but a session identifier, so it reveals nothing, and the wallet can choose which attributes to release for this verifier and this purpose, a property called selective disclosure. It also lets the verifier check that the wallet is live rather than a saved image. The cost is that both sides need connectivity or Bluetooth. The EU framework uses ISO/IEC 18013-5, the mobile driving licence standard, for the in-person case and OpenID for Verifiable Presentations for the online case; both start from a QR code.
Try it yourself
Scan an old boarding pass barcode with the decoder and read the BCBP fields: your name, booking reference, flight and seat, in plain text. Then think about who else could have read it.