Scottish QR Code Vaccination Status and EU Green Pass

Well, there’s a QR code doing the rounds that has the potential to open up our world of travel in a more trusted way. This is the green…

Scottish QR Code Vaccination Status and EU Green Pass

Well, there’s a QR code doing the rounds that has the potential to open up our world of travel in a more trusted way. This is the green pass, and which has been adopted in Scotland. The morals and ethics of this can be debated endlessly, but from a cryptography point-of-view, it is great to see a start towards building more trustworthy digital ways in allowing people to travel. A great thing is that it looks like the NHS have adopted the EU Green Pass format for vaccine status data.

First, we start with the basic data for the vaccine status report:

{
"1": "GB",
"4": 1992212161,
"6": 1425632973,
"-260": {
"1": {
"v": [
{
"ci": "URN:UVCI:01:GB:D23AD1B216A11133B272BEA32C426AC0#D",
"co": "GB",
"dn": 1,
"dt": "2021-01-14",
"is": "NHS Anywhere",
"ma": "ORG-110302699",
"mp": "EU/1/21/1529",
"sd": 2,
"tg": "341534114",
"vp": "3339315014"
}
],
"dob": "1977-01-10",
"nam": {
"fn": "SMITH",
"gn": "FRED SMITH",
"fnt": "SMITH",
"gnt": "FRED<SMITH"
},
"ver": "1.3.0"
}
}

This contains the date of birth of the person, their name, and the details of their vaccination. To then encode this into the QR, we create a signed object. In this following case, this is an EdDSA signature signed by a private key (such as from the NHS). The library used is COSE:

message='{"1": "GB","4": 1772210913,"6": 1830374921,"-260": { "1": {"v": [ {\"ci": \"URN:UVCI:01:GB:D36AF2C745B94400A176CF3E3B526BA#F","co": "GB","dn": 1,"dt": "2021-04-11","is": "NHS","ma": "ORG-100331689","mp": "EU/1/21/1529","sd": 2,"tg": "840539006","vp": "1119305005"}],"dob": "1977-01-04","nam": {"fn": "SMITH","gn": "FRED SMITH","fnt": "SMITH","gnt": "FRED<SMITH"},"ver": "1.3.0"}}}'
import zlib
import base45
from cose.messages import CoseMessage
from binascii import unhexlify, hexlify
from cose.messages import Sign1Message
from cose.keys import CoseKey
from cose.headers import Algorithm, KID
from cose.algorithms import EdDSA
from cose.keys.curves import Ed25519
from cose.keys.keyparam import KpKty, OKPKpD, OKPKpX, KpKeyOps, OKPKpCurve
from cose.keys.keytype import KtyOKP
from cose.keys.keyops import SignOp, VerifyOp
msg = Sign1Message(phdr = {Algorithm: EdDSA, KID: b'kid2'},payload = message.encode())
cose_key = {KpKty: KtyOKP,OKPKpCurve: Ed25519,KpKeyOps: [SignOp, VerifyOp],OKPKpD: unhexlify(b'9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'),OKPKpX: unhexlify(b'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a')}
cose_key = CoseKey.from_dict(cose_key)
msg.key = cose_key
en = msg.encode(tag=True,sign=True)

After this, we compress with zlib, and then encode with Base-45:

compressed = zlib.compress(en)
encoded = base45.b45encode(compressed)
print ("Code: ",encoded.decode())

This then gives us the code for the QR code. In this case, it is:

6BFX A0087I0ZQ2M95*7DF.4 4JUZ1U0OC0OL-5RO3E9VR/BVBKBPD*62: D*OH+$2$XEU-RI7A18PFNH-:DVN7 VJWBKB%JHBWN.D0-D2$4NV23QIH6O+P9N*SR:4*O3+:TH%D4R9H7D-%MIQ4OWDNTC6D261HBHQ445L52GG48TLY4QDEBYAK194L/STCA7M1KR61P8DSHW069.QN-G3 MHBJV.CI588 STC55J22Z9M2H%41R10REKDRI M9XAP8%ROZHKIA6*L5JNDU2JUII5LNV0MF7PI7RR35WT Y9E*SE:NV%LKHJ *8I40SDIA+G2X6EXQ.53/65.GQTG13M9%OQZPU .QS/DPIPG30$RIR226V8GCO566H7OK0PM+IIG15QQWKP9FM3ZN0XFIY9+2I09LXSMKOIE/0KSJ29LV%5LUL4BW:+B-J6RWPIEDL.RPO0CZ2CVSQAWIIVAETH3T  49E3YOREXJ.0P7FV5Z88DWXKUJWVRGD2T36MB5RAHYUQUL712W6S3Y9Z-TC4VY5SYTBGS361S6XR%AB.WVVFS++F

We then add “HC1:” to the string, and this is then simply written as a QR code. To decode we read the QR code data, and then decode the Base-45, decompress, and check the signature:

decoded = base45.b45decode(encoded.decode())
# decompress using zlib
decompressed = zlib.decompress(decoded)
cos = CoseMessage.decode(decompressed)
cos.key = cose_key
print ("Signature: ",cos.verify_signature())
print (cos.payload.decode())

And that’s it. Here’s the sample code:

https://asecuritysite.com/encryption/vaccine

Conclusions

Great work from NHS Scotland, but it is only the starting point in building toward a more trusted future.

Subscribe: https://billatnapier.medium.com/membership