This code was presented as part of the talk "A look inside the European Covid Green Certificate" at Codemotion 2021.
You can find all the slides at loige.link/green.
❤️
This code was presented as part of the talk "A look inside the European Covid Green Certificate" at Codemotion 2021.
You can find all the slides at loige.link/green.
❤️
[package] | |
name = "dgc-decode" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
base45 = "3.0.0" | |
ciborium = "0.2.0" | |
inflate = "0.4.5" | |
serde_json = "1.0.71" |
use ciborium::{de::from_reader, value::Value}; | |
use serde_json::to_string_pretty; | |
fn main() { | |
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4.P7*ZOP-IMJTI94F/8X*G3M9JUPY0BZW4Z*AK.GNNVR*G0C7PHBO335KN/NBEDBVBJ623323EAJ7UJ5PNDIB6PNS7B1DN%BBWC7WC7GB3683ML7SZ4ZI00T9UKPSH9WC5PF6846A$Q 76QW6A/98T5WBI$E9$UPV3Q.GUQ$9WC5R7ACB97C968ELZ5$DP6PP5IL*PP:+P*.1D9R8Q02-DE%QHOJ+PB/VSQOL9DLKWCZ3EBKDYGIZ J$XI4OIMEDTJCJKDLEDL9CZTAKBI/8D:8DKTDL+SQ05.$S6ZC0JBY63-C3F+LBQ99Q9E$BDZIA9JJ-JS7BYZJ92KG0TB9FNDA5KD9FED.B4JB3E9B9NNPCV9E6LFSD9C8J-QDSWNG4C-TLNKE$JDVPLW1KD0KCZGBKQCJE%RH5WAMSSR$F-75NXONQ84QV9/7/-LT1AIYBZGD$9RCLV-PTZ-K63ET-D1757H3GF9MV2N7WNQSY1SBZT-:81JJLHFQ-VG$HK00XWPD2"; | |
let no_prefix = remove_prefix(cert_data); | |
let decoded = decode_base45(no_prefix); | |
let decompressed = decompress(decoded); | |
let cwt_payload = get_cwt_payload(decompressed); | |
let parsed_payload = parse_cwt_payload(cwt_payload); | |
println!("{}", to_string_pretty(&parsed_payload).unwrap()); | |
} | |
fn parse_cwt_payload(data: Vec<u8>) -> Value { | |
from_reader(data.as_slice()).unwrap() | |
} | |
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { | |
let parsed: Value = from_reader(data.as_slice()).unwrap(); | |
let (tag, arr) = parsed.as_tag().unwrap(); | |
assert_eq!(tag, 18); | |
let arr = arr.as_array().unwrap(); | |
let payload = arr[2].as_bytes().unwrap(); | |
payload.clone() | |
} | |
fn decompress(data: Vec<u8>) -> Vec<u8> { | |
inflate::inflate_bytes_zlib(data.as_slice()).unwrap() // IRL use a Result! | |
} | |
fn decode_base45(data: &str) -> Vec<u8> { | |
base45::decode(data).unwrap() // IRL use a Result! | |
} | |
fn remove_prefix(data: &str) -> &str { | |
if data.len() < 4 || !&data.starts_with("HC1:") { | |
panic!("Invalid prefix"); // IRL use a Result! | |
} | |
&data[4..] | |
} |