Yesterday, California released their Digital Vaccine Record system for securely verifying residents'
COVID-19 vaccination status. I took a look at it and thought I'd write up my findings here. At a high level, the DVR consists of a QR code which contains a cryptographically-signed assertion in JSON Web
Token (JWT) format. I'll walk you through how to get one, how to
decode it, and what it contains in the rest of this article.
Getting one of the tokens is pretty easy; you just go to the Digital Vaccine Record website and put in your
name, date of birth, and the phone number or email address you gave when you got your vaccine. I got mine through
CVS, and, for whatever reason, they only provided my phone number to the state, not my email address. The state
will then send you an email or SMS containing a short-lived link to a website which will show a very large and
information-dense QR Code.
You can scan this QR code with the QR code scanner of your choice and you should get back some text like the
following:
shc:/56762909524320603460292437404460312229595326546034602925407728043360287028647167452228092861553055647103414321643241110839632106452403713377212638633677424237084126633945392929556404425627596537253338446120605736010645293353127074232853503870255550530362394304317059085244240537...
This very long string is a Smart Health Card token, which is the framework being used by several states. Let's
decode it with a little bit of Python!
First, create a virtualenv somewhere handy with python3 -m virtualenv venv
. Next, we'll install my forked copy of pyjwt
(which adds gzip support, as required for SHC) with ./venv/bin/pip install -e 'git+https://github.com/Roguelazer/pyjwt.git@deflate#egg=pyjwt[crypto]'
.
The following code will verify the signature on your SHC and print out the contents:
import jwt
import json
def decode(code):
if code.startswith('shc:/'):
code = code[5:]
# decode the numeric data into binary data
if len(code) % 2 != 0:
raise ValueError('code is not the right length')
d = []
for i in range(int(len(code) / 2)):
d.append(chr(int(code[i * 2] + code[(i * 2) + 1]) + 45))
d = ''.join(d)
# download the public keys from the CDPH website. Oddity: the .well-known/
# directory should be at the top-level, but it isn't!
jwks_client = jwt.PyJWKClient(
'https://myvaccinerecord.cdph.ca.gov/creds/.well-known/jwks.json'
)
# find the matching signing key based on the header
signing_key = jwks_client.get_signing_key_from_jwt(d)
data = jwt.decode(d, signing_key.key, algorithms=['ES256', 'RS256'])
return data
code = input('SHC code: ')
print(json.dumps(decode(code)))
If it works, you should get something like the following:
{
"iss": "https://myvaccinerecord.cdph.ca.gov/creds",
"nbf": 1624036526,
"vc": {
"type": [
"https://smarthealth.cards#health-card",
"https://smarthealth.cards#immunization",
"https://smarthealth.cards#covid19"
],
"credentialSubject": {
"fhirVersion": "4.0.1",
"fhirBundle": {
"resourceType": "Bundle",
"type": "collection",
"entry": [
{
"fullUrl": "resource:0",
"resource": {
"resourceType": "Patient",
"name": [
{
"family": "YOUR LAST NAME",
"given": [
"YOUR FIRST NAME"
]
}
],
"birthDate": "YOUR BIRTH DATE"
}
},
{
"fullUrl": "resource:1",
"resource": {
"resourceType": "Immunization",
"status": "completed",
"vaccineCode": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/cvx",
"code": "207"
}
]
},
"patient": {
"reference": "resource:0"
},
"occurrenceDateTime": "2021-04-19",
"performer": [
{
"actor": {
"display": "CVS CORPORATE"
}
}
],
"lotNumber": "036B21A"
}
},
{
"fullUrl": "resource:2",
"resource": {
"resourceType": "Immunization",
"status": "completed",
"vaccineCode": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/cvx",
"code": "207"
}
]
},
"patient": {
"reference": "resource:0"
},
"occurrenceDateTime": "2021-05-18",
"performer": [
{
"actor": {
"display": "CVS CORPORATE"
}
}
],
"lotNumber": " 025C21A"
}
}
]
}
}
}
}
This is pretty much what you might expect and is in line with, e.g., this very good article from the Mozilla
blog. It contains the
minimum amount of information required to identify someone (ideally paired with looking at their license or
something), it can be easily printed or otherwise stored offline, it's cryptographically verified using standard protocols and technologies. The only
thing that worries me is that it doesn't seem to have a human-readable field to encode what kind of vaccine it was that I received,
so if it turns out that one of the vaccines is ineffective against a variant and folks with that shot need a booster
in order to be considered "fully vaccinated", that will require some gymnastics. That's a pretty minor and
hypothetical concern, though.
Good on California for coming up with a reasonable and efficient system! I look forward for using it in
the future to be able to go to crowded places and feel confident that I'm not putting my un-vaccinatable son at risk. Hooray!