Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save s3rgeym/3f6925ce612167a567787522129c9dc8 to your computer and use it in GitHub Desktop.
Save s3rgeym/3f6925ce612167a567787522129c9dc8 to your computer and use it in GitHub Desktop.
Generates an (invalid) COVID-19 EU certificate
import base45
import cbor2
import zlib
from binascii import unhexlify
from cose.messages import Sign1Message
from cose.keys import CoseKey
# Specifications: https://ec.europa.eu/health/sites/default/files/ehealth/docs/covid-certificate_json_specification_en.pdf
payload = {
-260: {
1: {
'ver': '1.3.0',
'nam': {
'fn': 'LE BRON',
'gn': 'JAMES',
'fnt': 'LE<BRON', # Normalized, replace special chars by '<'
'gnt': 'JAMES', # Normalized, replace special chars by '<'
},
'dob': '1984-12-30', # Date of birth
'v': [ # 'v' stands for vaccination
{
'is': 'Bundesamt für Gesundheit (BAG)', # Authority issuing this certificate
'ci': 'urn:uvci:01:CH:CXDOS8PHU3BTI0HR368FKUMK', # Unique certificate ID assigned by the authority above
'co': 'Switzerland', # Country of vaccination
'dn': 2, # Number of doses injected
'dt': '2021-08-01', # Date of last injection
'sd': 2, # Number of doses required for full vaccination
'ma': 'ORG-100030215', # Manufacturer: Biontech Manufacturing GmbH
'mp': 'EU/1/20/1528', # Product: Comirnaty
'tg': '840539006', # Target disease: COVID-19
'vp': '1119349007', # Vaccine type: SARS-CoV-2 mRNA vaccine
},
],
}
}
}
# Sign message with a random key and algorithm (not known by verifying devices, hence invalid)
# https://pycose.readthedocs.io/en/latest/index.html
msg = Sign1Message(phdr = {"ALG": 'EDDSA'}, payload = cbor2.dumps(payload))
msg.key = CoseKey.from_dict({
"KTY": "OKP",
"CURVE": "ED25519",
"D": unhexlify(b'9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'), # Private key
"X": unhexlify(b'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'), # Public key
})
# Encoding
data = msg.encode()
data = zlib.compress(data, 9)
data = base45.b45encode(data)
data = "HC1:" + data.decode("ascii")
print(data)
# Prints out:
# HC1:NCFOXN*TS0BIP$FQP4EVPAN9I6T5XH4PIQJAZGA+1V2:U:PI/E2$4JY/KB:KVCNV375RV7Y4 CTEKFGVV0Z06ALT$I*U0:68TNP8EFY9AP$I/XK$M80I1PZB8L45QC:%OD3PVD98-OKSUG-K0C5Y/OCINAE1M8HVO2LFNAZ2PT0SHA5M9DT69T3ZY6WLIFO5YO9OUUMK9WLIK*L5R1$XJ/ L7L4N-V2V5 R7S+H G8DU1UMG9.PX+R.N8L/N:PIAVM:UPKP9QJA.IEAYUIMI4UUIMI.J9WVHWVH+ZE+R5AT1FTIPPA5NITK292W7*RBT1ON1EYH6I6IE9WT0K3M9UVZSVV*001HW%85B9-NT0 2$$0X4PCY0+-CVYCDEBD0HX2JR$4O1K%XGNZA45SQVMF13A/C1$9I38F0P9L41MDB2RJ5HTC6%CVE-M6+NHXL6LJ% 7GA3:9MYC9C26GUF8AP6-F838P4JEGW%44USCB6RXA1GR9- F9VE
# Store data in QR code, e.g. https://www.the-qrcode-generator.com
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment