Decoding the UK's NHS Test and Trace QR codes

Charlie Dancey

As persons in the UK may know, the government is rolling out a bold new strategy in the bid to slow down infection rates from Covid-19.

The lastest rollout is for QR codes to display at the point of sale. To obtain one, you create an account detailing the operator name, name of establishment, phone number and email address, you are then issued a QR code.

Being concerned about data security I am attempting to discover why the QR code I must display for persons using my cafe to "log in" with is 343 bytes long.

The QR code reads as follows:


There are a number of repeating sequences in the code such as "eyJ" and "pZCI6Il" which (I think) rules out the possibility that this is proper encryption.

My concern is that I am publicly displaying a lot of information, whereas it seems to me that a simply signature (like UKC19TRACING) plus a key into a database would be sufficient fo any rational way of implementing contact tracing.

So I have fired off a Freedom of Information request to the relevant government department (the UK Department of Health and Social care), but in the meantime I thought that greater experts than I might like to have a go at decrypting this.

Rob Napier

You're completely correct that the repeated eyJ strongly suggests this isn't just raw encrypted data, and has some structure. eyJ comes from the Base64 encoding of {" and almost always indicates that you're looking at Base64-encoded JSON. In this case, it's actually b64-encoded, but the eyJ pattern is the same. b64 is a slightly modified version of Base64.

As Topaco notes, the part after the UKC19TRACING:1: is a JWT. You can decode it at as the following:


  "alg": "ES256",
  "kid": "YrqeLTq8z-ofH5nzlaSGnYRfB9bu9yPlWYU_2b6qXOQ"

This tells you how it's signed, and the identifier of the key that signed it.


  "id": "V5VWX39R",
  "opn": "Pipley Barn Café",
  "adr": "Pipley Barn\nBrockham End\nLansdown",
  "pc": "BA19BZ",
  "vt": "008"

This is the signed payload. This isn't encrypted (and isn't meant to be). It's just b64-encoded and signed, along with the header.

You're correct that this could be implemented by a large database and a sparse identifier. The point of a JWT is that you don't need the database (and more importantly, don't need a mechanism for performing a database lookup). Because the data is signed, you can trust this payload was generated by an entity with access to the signing key. To validate this signature, you need the public key (generally as a JWK) for the given kid.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at


Login to comment


Related Related