Security & privacy
Signed QR codes and authenticity
A signed QR code pairs its payload with a digital signature that a verifying app checks against a trusted public key, proving who issued the code and that it was not altered. The EU Digital COVID Certificate worked this way. Signing proves authenticity, not privacy: the payload remains readable by any scanner.
The problem signatures solve
Anyone can generate a QR code claiming anything. A code's visual style, logo and frame prove nothing. They are trivially copied, which is why sticker substitution attacks work. When a code is a ticket, a certificate or a proof of provenance, "does it scan" is the wrong question; the right one is "who issued this, and has it been altered?", and only cryptography answers it.
How a signed QR code works
The payload carries two parts: the claims, and a digital signature over them made with the issuer's private key. A verifying app holds the corresponding public key and checks, at scan time, that the signature matches. The common open pattern is JWS/JWT: the same structure used for web tokens, dropped into a code:
header.payload.signature (base64url, signed with e.g. ES256)
Any tampering (a changed seat number, an extended expiry) breaks the signature; a forger without the private key cannot produce a valid one. What the verifier trusts is the key, not the pixels.
The flagship example: the EU Digital COVID Certificate
The largest deployment of signed QR codes to date is well documented and public: the EU
Digital COVID Certificate encoded its claims as CBOR, signed them with COSE, compressed
the result and rendered it as text with the HC1: prefix. The detail worth savouring:
it used base45, an encoding chosen specifically because its 45-character alphabet fits
QR alphanumeric mode, which packs about 45% more characters
per code than byte mode, a spec-level optimisation covered in
data encoding modes. Verifier apps carried the public
keys of every issuing country and checked signatures offline.
SQRC: the closed variant
Denso Wave's SQRC takes a proprietary route: a code with a public part any scanner can read and a private part that only licensed readers holding the right cryptographic key can decode. That is access control as much as authenticity, and it binds you to specific hardware and licensing. For most authenticity problems, the open signature-in-payload pattern does the job without special readers.
What signing does (and does not) give you
| Property | Signed QR delivers it? |
|---|---|
| Authenticity (who issued it) | Yes |
| Integrity (unaltered since issue) | Yes |
| Privacy (payload hidden) | No: anyone can still read the claims |
| Revocation | Only with extra infrastructure (key or ID blocklists) |
| Protection via ordinary camera apps | No, a stock camera just shows the text |
That last row is the deployment catch: signatures only help where scanning happens in a verifier app that checks them. A door steward with a stock camera app sees gibberish that "looks official", which is no security at all.
Build sketch for developers
- Keep claims compact, CBOR or terse JSON. Signature overhead is real: an ES256 signature alone is 64 raw bytes (~86 base64url characters), plus header, which pushes codes up several versions.
- Sign server-side at issue time; verify offline in the app with pinned public keys. Key distribution and rotation is the actual hard part, design it first.
- Test the full loop: generate, render, decode, verify, the same discipline as a decode-verify check, with signature validation appended.
- For physical goods, signing pairs naturally with product authentication flows; for physical substitution attacks, pair with tamper-evident labels, a valid signature on a relocated sticker is still a valid signature.
FAQ
What is a signed QR code?
A code whose payload includes a digital signature made with the issuer's private key. A verifying app checks the signature against the issuer's public key, proving who created the code and that its contents have not been changed since.
Can a signed QR code be faked?
The signature cannot be forged without the issuer's private key. What an attacker can do is copy a genuine code in its entirety: signing proves origin and integrity, not uniqueness or placement, so duplication and relocation need separate defences.
Do signed QR codes work with a normal camera app?
No. A stock camera app just displays the encoded text without checking anything. Signatures only add security when scanning happens in a verifier app that validates them against trusted keys.
What did the EU COVID certificate QR contain?
Health claims encoded as CBOR, signed with COSE by the issuing country, compressed, and rendered as base45 text with an HC1: prefix. Verifier apps checked the signature offline against a distributed set of national public keys.
Try it: free, no signup
Related
- Are QR codes safe?, Scanning a QR code is safe in itself: it decodes text and nothing else. The risk is entirely in what you do next. A code cannot install software, dial,…
- Tamper-evident QR labels, Destructible vinyl, void laminates and holographic overlays make QR sticker swaps visible for pennies per label, if you pair them with a physical audit routine.
- The security model of 2FA setup QR codes, The 2FA setup QR carries your shared secret in plain text, shown once. What the otpauth URI contains, how TOTP works, and how to handle the exposure window.
- QR codes for product authentication: what works and what doesn't, Anti-counterfeit QR tiers compared (shared codes, unique per-unit codes, signed codes), and the honest limits: a copied code copies the authentic page.