SlideShare una empresa de Scribd logo
1 de 234
Descargar para leer sin conexión
A look inside the
European Covid Green Certificate
Luciano Mammino ( )
@loige
2021-12-01
loige.link/green
1
Get these slides!
loige
loige.link/green
2
Let me introduce myself first...
3
Let me introduce myself first...
👋I'm Luciano ( 🍕🍝 )
3
Let me introduce myself first...
👋I'm Luciano ( 🍕🍝 )
Senior Architect @ fourTheorem (Dublin )
3
Let me introduce myself first...
👋I'm Luciano ( 🍕🍝 )
Senior Architect @ fourTheorem (Dublin )
nodejsdp.link
📔Co-Author of Node.js Design Patterns  👉
3
Let me introduce myself first...
👋I'm Luciano ( 🍕🍝 )
Senior Architect @ fourTheorem (Dublin )
nodejsdp.link
📔Co-Author of Node.js Design Patterns  👉
Let's connect!
  (blog)
  (twitter)
  (twitch)
  (github)
loige.co
@loige
loige
lmammino
3
We are business focused technologists that
deliver.
 |  |
Accelerated Serverless AI as a Service Platform Modernisation
We are hiring: do you want to ?
work with us
loige 4
Disclaimers
loige 5
Disclaimers
loige
🤓I am not involved with the DGC working group
 
5
Disclaimers
loige
🤓I am not involved with the DGC working group
 
😢COVID has been tough on everyone,
      we'll try to focus only on the tech here!
5
Agenda + Goals
loige 6
Agenda + Goals
loige
1. Needs and principles
2. 🗝Cryptographic model
3. 📦The data
4. 🧅Layers of encoding
5. 🛠Decoding in Rust
6
Agenda + Goals
loige
1. Needs and principles
2. 🗝Cryptographic model
3. 📦The data
4. 🧅Layers of encoding
5. 🛠Decoding in Rust
🤨Learn some cool technologies
🧐Learn a tiny bit of Rust
🤓Be nerdy and have fun!
6
The need for a digital certificate in
the COVID age
loige 7
The need for a digital certificate in
the COVID age
loige 8
The need for a digital certificate in
the COVID age
loige
😷We need a system to quickly provide a proof against COVID
      (Vaccination, negative test, proof of recovery) 
8
The need for a digital certificate in
the COVID age
loige
😷We need a system to quickly provide a proof against COVID
      (Vaccination, negative test, proof of recovery) 
It needs to be personal, easy to carry around (digital),
       easy to issue and to validate
8
The need for a digital certificate in
the COVID age
loige
😷We need a system to quickly provide a proof against COVID
      (Vaccination, negative test, proof of recovery) 
It needs to be personal, easy to carry around (digital),
       easy to issue and to validate
🌎It needs to be secure against forgery and work across countries
8
The EU Covid Green Pass
a.k.a. 
Electronic Health Certificates
(HCERT)
 
loige.link/hcert-spec
loige 9
Electronic Health Certificates (HCERT)
Requirements & Guiding Principles
loige 10
Electronic Health Certificates (HCERT)
Requirements & Guiding Principles
loige
✍Signed data with machine readable content
10
Electronic Health Certificates (HCERT)
Requirements & Guiding Principles
loige
✍Signed data with machine readable content
📃Use compact encoding
10
Electronic Health Certificates (HCERT)
Requirements & Guiding Principles
loige
✍Signed data with machine readable content
📃Use compact encoding
🤲Based on open standards
10
Asymmetric cryptographic signatures
loige 11
Asymmetric cryptographic signatures
loige
🤫Private Key
101010101000101010010...
11
Asymmetric cryptographic signatures
loige
🤫Private Key 📢Public Key
101010101000101010010... 0101010101010101010101...
11
Asymmetric cryptographic signatures
loige
🤫Private Key 📢Public Key
🔗
101010101000101010010... 0101010101010101010101...
11
Asymmetric cryptographic signatures
loige
🤫Private Key 📢Public Key
101010101000101010010... 0101010101010101010101...
12
Asymmetric cryptographic signatures
loige
🤫Private Key 📢Public Key
101010101000101010010... 0101010101010101010101...
12
Asymmetric cryptographic signatures
loige
🤫Private Key 📢Public Key
101010101000101010010... 0101010101010101010101...
The owner of the private
key signs the document
12
Asymmetric cryptographic signatures
loige
🤫Private Key 📢Public Key
101010101000101010010... 0101010101010101010101...
The owner of the private
key signs the document
12
Asymmetric cryptographic signatures
loige
🤫Private Key 📢Public Key
101010101000101010010... 0101010101010101010101...
The owner of the private
key signs the document
Anyone can validate the
signature using the public
key
12
Asymmetric cryptographic signatures
loige
🤫Private Key 📢Public Key
101010101000101010010... 0101010101010101010101...
The owner of the private
key signs the document
Anyone can validate the
signature using the public
key
12
What's inside a certificate?
loige 13
What's inside a certificate?
loige 13
What's inside a certificate?
loige
Cryptographic header (Key Id, Algorithm)
13
What's inside a certificate?
loige
DGC container
Cryptographic header (Key Id, Algorithm)
13
What's inside a certificate?
loige
DGC container
Cryptographic header (Key Id, Algorithm)
Cryptographic Signature
13
What's inside a certificate?
loige
DGC container
Cryptographic header (Key Id, Algorithm)
Cryptographic Signature
Header (Issuer, Issue date, expiry date)
13
What's inside a certificate?
loige
DGC container
Cryptographic header (Key Id, Algorithm)
Cryptographic Signature
Header (Issuer, Issue date, expiry date)
13
Certificates list
Personal data (name, surname, DoB)
What's inside a certificate?
loige
DGC container
Cryptographic header (Key Id, Algorithm)
Cryptographic Signature
Header (Issuer, Issue date, expiry date)
13
Certificates list
vaccine, test, or recovery data
Personal data (name, surname, DoB)
An example
loige loige.link/green-examples 14
An example
loige loige.link/green-examples 15
{
"1": "DK",
"4": 1625054000,
"6": 1622462000,
"-260": {
"ver":"1.0.0",
"nam":{
"fn":"Klaus",
"fnt":"KLAUS",
"gn":"Jørgensen",
"gnt":"JOERGENSEN"
},
"dob":"1983-01-06",
"v":[
{
"tg":"840539006",
"vp":"1119349007",
"mp":"EU/1/20/1528",
"ma":"ORG-100030215",
"dn":2,
"sd":2,
"dt":"2021-05-03",
"co":"DK",
"is":"Danish Health Data Authority",
"ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A"
}
]
}
}
An example
loige loige.link/green-examples 15
{
"1": "DK",
"4": 1625054000,
"6": 1622462000,
"-260": {
"ver":"1.0.0",
"nam":{
"fn":"Klaus",
"fnt":"KLAUS",
"gn":"Jørgensen",
"gnt":"JOERGENSEN"
},
"dob":"1983-01-06",
"v":[
{
"tg":"840539006",
"vp":"1119349007",
"mp":"EU/1/20/1528",
"ma":"ORG-100030215",
"dn":2,
"sd":2,
"dt":"2021-05-03",
"co":"DK",
"is":"Danish Health Data Authority",
"ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A"
}
]
}
}
An example
loige loige.link/green-examples
DGC Header
15
{
"1": "DK",
"4": 1625054000,
"6": 1622462000,
"-260": {
"ver":"1.0.0",
"nam":{
"fn":"Klaus",
"fnt":"KLAUS",
"gn":"Jørgensen",
"gnt":"JOERGENSEN"
},
"dob":"1983-01-06",
"v":[
{
"tg":"840539006",
"vp":"1119349007",
"mp":"EU/1/20/1528",
"ma":"ORG-100030215",
"dn":2,
"sd":2,
"dt":"2021-05-03",
"co":"DK",
"is":"Danish Health Data Authority",
"ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A"
}
]
}
}
An example
loige loige.link/green-examples
Personal info
DGC Header
15
{
"1": "DK",
"4": 1625054000,
"6": 1622462000,
"-260": {
"ver":"1.0.0",
"nam":{
"fn":"Klaus",
"fnt":"KLAUS",
"gn":"Jørgensen",
"gnt":"JOERGENSEN"
},
"dob":"1983-01-06",
"v":[
{
"tg":"840539006",
"vp":"1119349007",
"mp":"EU/1/20/1528",
"ma":"ORG-100030215",
"dn":2,
"sd":2,
"dt":"2021-05-03",
"co":"DK",
"is":"Danish Health Data Authority",
"ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A"
}
]
}
}
An example
loige loige.link/green-examples
Personal info
Vaccine info
DGC Header
15
Layered
encoding
loige 16
🧅
Layered
encoding
loige
QRCODE ASCII mode
16
🧅
Layered
encoding
loige
QRCODE ASCII mode
Prefix + Base45 encoding
16
🧅
Layered
encoding
loige
QRCODE ASCII mode
Prefix + Base45 encoding
Zlib compression
16
🧅
Layered
encoding
loige
QRCODE ASCII mode
Prefix + Base45 encoding
Zlib compression
CWT signed data (COSE)
16
🧅
Layered
encoding
loige
QRCODE ASCII mode
Prefix + Base45 encoding
Zlib compression
CWT signed data (COSE)
CBOR document
16
🧅
loige
QRCode content
17
loige
HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-36
5KN-TMLV4.P7*ZOP-IMJTI94F/8X*G3M9JUPY0BZW4Z
*AK.GNNVR*G0C7PHBO335KN/NBEDBVBJ623323EAJ7U
J5PNDIB6PNS7B1DN%BBWC7WC7GB3683ML7SZ4ZI00T9
UKPSH9WC5PF6846A$Q 76QW6A/98T5WBI$E9$UPV3Q.
GUQ$9WC5R7ACB97C968ELZ5$DP6PP5IL*PP:+P*.1D9
R8Q02-DE%QHOJ+PB/VSQOL9DLKWCZ3EBKDYGIZ J$XI
4OIMEDTJCJKDLEDL9CZTAKBI/8D:8DKTDL+SQ05.$S6
ZC0JBY63-C3F+LBQ99Q9E$BDZIA9JJ-JS7BYZJ92KG0
TB9FNDA5KD9FED.B4JB3E9B9NNPCV9E6LFSD9C8J-QD
SWNG4C-TLNKE$JDVPLW1KD0KCZGBKQCJE%RH5WAMSSR
$F-75NXONQ84QV9/7/-LT1AIYBZGD$9RCLV-PTZ-K63
ET-D1757H3GF9MV2N7WNQSY1SBZT-:81JJLHFQ-VG$H
K00XWPD2
QRCode content
17
loige
HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-36
5KN-TMLV4.P7*ZOP-IMJTI94F/8X*G3M9JUPY0BZW4Z
*AK.GNNVR*G0C7PHBO335KN/NBEDBVBJ623323EAJ7U
J5PNDIB6PNS7B1DN%BBWC7WC7GB3683ML7SZ4ZI00T9
UKPSH9WC5PF6846A$Q 76QW6A/98T5WBI$E9$UPV3Q.
GUQ$9WC5R7ACB97C968ELZ5$DP6PP5IL*PP:+P*.1D9
R8Q02-DE%QHOJ+PB/VSQOL9DLKWCZ3EBKDYGIZ J$XI
4OIMEDTJCJKDLEDL9CZTAKBI/8D:8DKTDL+SQ05.$S6
ZC0JBY63-C3F+LBQ99Q9E$BDZIA9JJ-JS7BYZJ92KG0
TB9FNDA5KD9FED.B4JB3E9B9NNPCV9E6LFSD9C8J-QD
SWNG4C-TLNKE$JDVPLW1KD0KCZGBKQCJE%RH5WAMSSR
$F-75NXONQ84QV9/7/-LT1AIYBZGD$9RCLV-PTZ-K63
ET-D1757H3GF9MV2N7WNQSY1SBZT-:81JJLHFQ-VG$H
K00XWPD2
QRCode content "HC1:" (prefix)
17
loige
HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-36
5KN-TMLV4.P7*ZOP-IMJTI94F/8X*G3M9JUPY0BZW4Z
*AK.GNNVR*G0C7PHBO335KN/NBEDBVBJ623323EAJ7U
J5PNDIB6PNS7B1DN%BBWC7WC7GB3683ML7SZ4ZI00T9
UKPSH9WC5PF6846A$Q 76QW6A/98T5WBI$E9$UPV3Q.
GUQ$9WC5R7ACB97C968ELZ5$DP6PP5IL*PP:+P*.1D9
R8Q02-DE%QHOJ+PB/VSQOL9DLKWCZ3EBKDYGIZ J$XI
4OIMEDTJCJKDLEDL9CZTAKBI/8D:8DKTDL+SQ05.$S6
ZC0JBY63-C3F+LBQ99Q9E$BDZIA9JJ-JS7BYZJ92KG0
TB9FNDA5KD9FED.B4JB3E9B9NNPCV9E6LFSD9C8J-QD
SWNG4C-TLNKE$JDVPLW1KD0KCZGBKQCJE%RH5WAMSSR
$F-75NXONQ84QV9/7/-LT1AIYBZGD$9RCLV-PTZ-K63
ET-D1757H3GF9MV2N7WNQSY1SBZT-:81JJLHFQ-VG$H
K00XWPD2
QRCode content "HC1:" (prefix)
Binary data encoded in
Base45
17
Base45
loige 18
loige
Base45
19
loige
Allows to encode binary data in text format (ASCII)
Base45
19
loige
Allows to encode binary data in text format (ASCII)
Like Base64, but it uses 45 characters instead:
Base45
19
loige
Allows to encode binary data in text format (ASCII)
Like Base64, but it uses 45 characters instead:
loige.link/base45-explained
Base45
19
Base45
loige 20
Base45
loige
01001001 00100000 01100111
01101111 01110100 00100000
01101101 01111001 00100000
01110011 01101000 01101111
01110100 01110011 00100000
11011000 00111101
Some binary data
20
Base45
loige
01001001 00100000 01100111
01101111 01110100 00100000
01101101 01111001 00100000
01110011 01101000 01101111
01110100 01110011 00100000
11011000 00111101
Some binary data
20
Base45
loige
01001001 00100000 01100111
01101111 01110100 00100000
01101101 01111001 00100000
01110011 01101000 01101111
01110100 01110011 00100000
11011000 00111101
UTF8 (17 bytes)
I got my shots 💉
Some binary data
20
Base45
loige
01001001 00100000 01100111
01101111 01110100 00100000
01101101 01111001 00100000
01110011 01101000 01101111
01110100 01110011 00100000
11011000 00111101
UTF8 (17 bytes)
I got my shots 💉
Hex (38 bytes)
49 20 67 6f 74 20 6d 79 20 73 68
6f 74 73 20 f0 9f 92 89
Some binary data
20
Base45
loige
01001001 00100000 01100111
01101111 01110100 00100000
01101101 01111001 00100000
01110011 01101000 01101111
01110100 01110011 00100000
11011000 00111101
UTF8 (17 bytes)
I got my shots 💉
Hex (38 bytes)
49 20 67 6f 74 20 6d 79 20 73 68
6f 74 73 20 f0 9f 92 89
Base64 (28 bytes)
SSBnb3QgbXkgc2hvdHMg8J+SiQ==
Some binary data
20
Base45
loige
01001001 00100000 01100111
01101111 01110100 00100000
01101101 01111001 00100000
01110011 01101000 01101111
01110100 01110011 00100000
11011000 00111101
UTF8 (17 bytes)
I got my shots 💉
Hex (38 bytes)
49 20 67 6f 74 20 6d 79 20 73 68
6f 74 73 20 f0 9f 92 89
Base64 (28 bytes)
SSBnb3QgbXkgc2hvdHMg8J+SiQ==
Base45 (29 bytes)
0B9J3DSUEZ$DR4459DLWEH74Z7K23
Some binary data
20
loige
loige.link/base45-rfc
"A QR-code is used to encode text as a graphical image. [...] QR-codes
cannot be used to encode arbitrary binary data directly.  [...] Compared
to already established Base64, Base32 and Base16 encoding schemes
[...], the Base45 scheme described in this document offer a more
compact QR-code encoding"
Base45
21
loige
Base45
22
loige
Base45
NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-
TMLV4.P7*ZOP-IMJTI94F/8X*G3M9JUPY0BZW4Z*AK.
GNNVR*G0C7PHBO335KN/NBEDBVBJ623323EAJ7UJ5PN
DIB6PNS7B1DN%BBWC7WC7GB3683ML7SZ4ZI00T9UKPS
H9WC5PF6846A$Q 76QW6A/98T5WBI$E9$UPV3Q.GUQ$
9WC5R7ACB97C968ELZ5$DP6PP5IL*PP:+P*.1D9R8Q0
2-DE%QHOJ+PB/VSQOL9DLKWCZ3EBKDYGIZ J$XI4OIM
EDTJCJKDLEDL9CZTAKBI/8D:8DKTDL+SQ05.$S6ZC0J
BY63-C3F+LBQ99Q9E$BDZIA9JJ-JS7BYZJ92KG0TB9F
NDA5KD9FED.B4JB3E9B9NNPCV9E6LFSD9C8J-QDSWNG
4C-TLNKE$JDVPLW1KD0KCZGBKQCJE%RH5WAMSSR$F-7
5NXONQ84QV9/7/-LT1AIYBZGD$9RCLV-PTZ-K63ET-D
1757H3GF9MV2N7WNQSY1SBZT-:81JJLHFQ-VG$HK00X
WPD2
22
loige
Base45
NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-
TMLV4.P7*ZOP-IMJTI94F/8X*G3M9JUPY0BZW4Z*AK.
GNNVR*G0C7PHBO335KN/NBEDBVBJ623323EAJ7UJ5PN
DIB6PNS7B1DN%BBWC7WC7GB3683ML7SZ4ZI00T9UKPS
H9WC5PF6846A$Q 76QW6A/98T5WBI$E9$UPV3Q.GUQ$
9WC5R7ACB97C968ELZ5$DP6PP5IL*PP:+P*.1D9R8Q0
2-DE%QHOJ+PB/VSQOL9DLKWCZ3EBKDYGIZ J$XI4OIM
EDTJCJKDLEDL9CZTAKBI/8D:8DKTDL+SQ05.$S6ZC0J
BY63-C3F+LBQ99Q9E$BDZIA9JJ-JS7BYZJ92KG0TB9F
NDA5KD9FED.B4JB3E9B9NNPCV9E6LFSD9C8J-QDSWNG
4C-TLNKE$JDVPLW1KD0KCZGBKQCJE%RH5WAMSSR$F-7
5NXONQ84QV9/7/-LT1AIYBZGD$9RCLV-PTZ-K63ET-D
1757H3GF9MV2N7WNQSY1SBZT-:81JJLHFQ-VG$HK00X
WPD2
Base45
Decode
22
loige
Base45
NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-
TMLV4.P7*ZOP-IMJTI94F/8X*G3M9JUPY0BZW4Z*AK.
GNNVR*G0C7PHBO335KN/NBEDBVBJ623323EAJ7UJ5PN
DIB6PNS7B1DN%BBWC7WC7GB3683ML7SZ4ZI00T9UKPS
H9WC5PF6846A$Q 76QW6A/98T5WBI$E9$UPV3Q.GUQ$
9WC5R7ACB97C968ELZ5$DP6PP5IL*PP:+P*.1D9R8Q0
2-DE%QHOJ+PB/VSQOL9DLKWCZ3EBKDYGIZ J$XI4OIM
EDTJCJKDLEDL9CZTAKBI/8D:8DKTDL+SQ05.$S6ZC0J
BY63-C3F+LBQ99Q9E$BDZIA9JJ-JS7BYZJ92KG0TB9F
NDA5KD9FED.B4JB3E9B9NNPCV9E6LFSD9C8J-QDSWNG
4C-TLNKE$JDVPLW1KD0KCZGBKQCJE%RH5WAMSSR$F-7
5NXONQ84QV9/7/-LT1AIYBZGD$9RCLV-PTZ-K63ET-D
1757H3GF9MV2N7WNQSY1SBZT-:81JJLHFQ-VG$HK00X
WPD2
Base45
Decode
Compressed binary data
22
Zlib compression
loige 23
Zlib compression
loige
"zlib is designed to be a free, general-purpose, legally
unencumbered -- that is, not covered by any patents -- lossless
data-compression library for use on virtually any computer
hardware and operating system"
zlib.net
24
Zlib compression
loige 25
Zlib compression
loige
Compressed binary data
25
Zlib compression
loige
Zlib inflate
Compressed binary data
25
Zlib compression
loige
Zlib inflate
Compressed binary data Decompressed binary data
25
Zlib compression
loige 26
Zlib compression
loige 26
Zlib compression
loige
👀We start to see
some "readable"
information!
26
COSE / CWT
loige
CBOR Object Signing and Encryption / CBOR Web Token
27
CBOR !? 🤔
loige
But wait, what the heck is
✋
28
CBOR
loige
TLDR; Like JSON but in binary!
loige.link/cbor-rfc
29
JSON
loige
A schema-less data format where a value can be:
Null
Boolean
Number
String
Array
Object
null
true
-17.34
"A programmer walks into a bar..."
["foo", 1.23, null, false, [22]]
{"foo": "bar", "manyvals": [1,2,3], "nested": {}}
30
CBOR
loige
A schema-less binary data format where a value can be:
Null
Boolean
Number
String Text
Array
Object Map
F6
F5
fbc031570a3d70a3d7
7820412070726f6772616d6d65722077616c6b7320696e746f2061206261722e2e2e
8563666f6ffb3ff3ae147ae147aef6f48116
a363666f6f63626172686d616e7976616c7383010203666e6573746564a0
31
CBOR
loige
It also supports:
Byte String (a sequence of raw bytes)
Tags (annotations that allow to create new types)
32
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
}
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo":
}
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo": "bar",
}
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo": "bar",
"manyvals":
}
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo": "bar",
"manyvals": [
}
],
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo": "bar",
"manyvals": [
}
],
1,
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo": "bar",
"manyvals": [
}
],
1, 2,
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo": "bar",
"manyvals": [
}
],
1, 2, 3
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo": "bar",
"manyvals": [
}
],
"nested":
1, 2, 3
33
CBOR
loige
An example:
A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0
{
"foo": "bar",
"manyvals": [
}
],
"nested": {}
1, 2, 3
33
COSE / CWT
loige
CBOR Object Signing and Encryption / CBOR Web Token
ok... again 😅
34
COSE
loige
CBOR Object Signing and Encryption
35
COSE
loige
CBOR Object Signing and Encryption
COSE (inspired by ) defines CBOR-based protocols for:
JOSE
35
COSE
loige
CBOR Object Signing and Encryption
COSE (inspired by ) defines CBOR-based protocols for:
JOSE
Encrypted data
35
COSE
loige
CBOR Object Signing and Encryption
COSE (inspired by ) defines CBOR-based protocols for:
JOSE
Encrypted data
Cryptographic signed data
35
COSE
loige
CBOR Object Signing and Encryption
COSE (inspired by ) defines CBOR-based protocols for:
JOSE
Encrypted data
Cryptographic signed data
MACed data
35
COSE
loige
loige.link/cose-rfc
CBOR Object Signing and Encryption
COSE (inspired by ) defines CBOR-based protocols for:
JOSE
Encrypted data
Cryptographic signed data
MACed data
35
CWT
loige
CBOR Web Token
36
CWT
loige
Like but for CBOR
JWT
CBOR Web Token
36
CWT
loige
Like but for CBOR
JWT
Defines a protocol for transferring claims between parties
CBOR Web Token
36
CWT
loige
Like but for CBOR
JWT
Defines a protocol for transferring claims between parties
CBOR Web Token
Claims are digitally signed for authenticity
36
CWT
loige
Like but for CBOR
JWT
loige.link/cwt-rfc
Defines a protocol for transferring claims between parties
CBOR Web Token
Claims are digitally signed for authenticity
36
CWT
loige
CBOR Web Token
37
CWT
loige
A CWT is made of 4 parts:
CBOR Web Token
37
CWT
loige
A CWT is made of 4 parts:
Protected header
CBOR Web Token
37
CWT
loige
A CWT is made of 4 parts:
Protected header
CBOR Web Token
Non protected header
37
CWT
loige
A CWT is made of 4 parts:
Protected header
CBOR Web Token
Non protected header
Payload
37
CWT
loige
A CWT is made of 4 parts:
Protected header
CBOR Web Token
Non protected header
Payload
Signature
37
CWT
loige
A CWT is encoded as a (tagged) CBOR array with 4 values:
Protected header (binary string)
CBOR Web Token
Non protected header (map)
Payload (binary string)
Signature (binary string)
38
loige 39
loige 39
loige
CWT tag
39
loige
CWT tag
39
loige
Array (length 4)
CWT tag
39
loige
Array (length 4)
CWT tag
39
Protected
header
Binary String
loige
Array (length 4)
CWT tag
39
Protected
header
Binary String
loige
Array (length 4)
CWT tag
39
Protected
header
Binary String
loige
Array (length 4)
CWT tag
39
Unprotected header
Map (length 0)
Protected
header
Binary String
loige
Array (length 4)
CWT tag
39
Unprotected header
Map (length 0)
Protected
header
Binary String
loige
Array (length 4)
CWT tag
39
Unprotected header
Map (length 0)
Payload
Binary String
Protected
header
Binary String
loige
Array (length 4)
CWT tag
39
Unprotected header
Map (length 0)
Payload
Binary String
Protected
header
Binary String
loige
Array (length 4)
CWT tag
39
Unprotected header
Map (length 0)
Payload
Binary String
Signature
Binary String
loige
CWT payload
40
loige
CWT payload
40
loige
CWT payload
Binary String follows (CBOR Encoded)
40
loige
CWT payload
{
"1": "DK",
"4": 1625054000,
"6": 1622462000,
"-260": {
"ver":"1.0.0",
"nam":{
"fn":"Klaus",
"fnt":"KLAUS",
"gn":"Jørgensen",
"gnt":"JOERGENSEN"
},
"dob":"1983-01-06",
"v":[
{
"tg":"840539006",
"vp":"1119349007",
"mp":"EU/1/20/1528",
"ma":"ORG-100030215",
"dn":2,
"sd":2,
"dt":"2021-05-03",
"co":"DK",
"is":"Danish Health Data Authority",
"ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A"
}
]
}
}
Binary String follows (CBOR Encoded)
CBOR decode
    (to JSON)
40
loige
CWT payload
{
"1": "DK",
"4": 1625054000,
"6": 1622462000,
"-260": {
"ver":"1.0.0",
"nam":{
"fn":"Klaus",
"fnt":"KLAUS",
"gn":"Jørgensen",
"gnt":"JOERGENSEN"
},
"dob":"1983-01-06",
"v":[
{
"tg":"840539006",
"vp":"1119349007",
"mp":"EU/1/20/1528",
"ma":"ORG-100030215",
"dn":2,
"sd":2,
"dt":"2021-05-03",
"co":"DK",
"is":"Danish Health Data Authority",
"ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A"
}
]
}
}
Binary String follows (CBOR Encoded)
CBOR decode
    (to JSON)
40
How to decode - quick recap
loige 41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
2. Base45 decode
41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
2. Base45 decode
3. Zlib decompress
41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
2. Base45 decode
3. Zlib decompress
4. Parse CWT
41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
2. Base45 decode
3. Zlib decompress
4. Parse CWT
5. Parse CWT Payload as CBOR
41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
2. Base45 decode
3. Zlib decompress
4. Parse CWT
5. Parse CWT Payload as CBOR
6. Party hard! 🥳
41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
2. Base45 decode
3. Zlib decompress
4. Parse CWT
5. Parse CWT Payload as CBOR
6. Party hard! 🥳
41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
2. Base45 decode
3. Zlib decompress
4. Parse CWT
5. Parse CWT Payload as CBOR
6. Party hard! 🥳
Hey, let's implement this...
41
How to decode - quick recap
loige
1. Remove "HC1:" prefix
2. Base45 decode
3. Zlib decompress
4. Parse CWT
5. Parse CWT Payload as CBOR
6. Party hard! 🥳
Hey, let's implement this... in Rust!
41
loige
cargo new dgc-decode
Project bootstrap
42
// src/main.rs
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
todo!()
// 1. Remove "HC1:" prefix
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
1
2
3
4
5
6
7
8
9
10
11
loige 43
// src/main.rs
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
todo!()
// 1. Remove "HC1:" prefix
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
1
2
3
4
5
6
7
8
9
10
11
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
// src/main.rs
1
2
fn main() {
3
4
todo!()
5
// 1. Remove "HC1:" prefix
6
// 2. Base45 decode
7
// 3. Zlib decompress
8
// 4. Parse CWT
9
// 5. Parse CWT Payload as CBOR
10
}
11
loige 43
// src/main.rs
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
todo!()
// 1. Remove "HC1:" prefix
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
1
2
3
4
5
6
7
8
9
10
11
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
// src/main.rs
1
2
fn main() {
3
4
todo!()
5
// 1. Remove "HC1:" prefix
6
// 2. Base45 decode
7
// 3. Zlib decompress
8
// 4. Parse CWT
9
// 5. Parse CWT Payload as CBOR
10
}
11
todo!()
// 1. Remove "HC1:" prefix
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
// src/main.rs
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
5
6
7
8
9
10
}
11
loige 43
// src/main.rs
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
todo!()
// 1. Remove "HC1:" prefix
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
1
2
3
4
5
6
7
8
9
10
11
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
// src/main.rs
1
2
fn main() {
3
4
todo!()
5
// 1. Remove "HC1:" prefix
6
// 2. Base45 decode
7
// 3. Zlib decompress
8
// 4. Parse CWT
9
// 5. Parse CWT Payload as CBOR
10
}
11
todo!()
// 1. Remove "HC1:" prefix
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
// src/main.rs
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
5
6
7
8
9
10
}
11
// src/main.rs
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
todo!()
// 1. Remove "HC1:" prefix
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
1
2
3
4
5
6
7
8
9
10
11
loige 43
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
todo!()
// remove "HC1:" prefix and return remaining string
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
loige 44
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
todo!()
// remove "HC1:" prefix and return remaining string
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let no_prefix = remove_prefix(cert_data);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
3
todo!();
4
// 2. Base45 decode
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn remove_prefix(data: &str) -> &str {
11
todo!()
12
// remove "HC1:" prefix and return remaining string
13
}
14
loige 44
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
todo!()
// remove "HC1:" prefix and return remaining string
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let no_prefix = remove_prefix(cert_data);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
3
todo!();
4
// 2. Base45 decode
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn remove_prefix(data: &str) -> &str {
11
todo!()
12
// remove "HC1:" prefix and return remaining string
13
}
14
fn remove_prefix(data: &str) -> &str {
todo!()
// remove "HC1:" prefix and return remaining string
}
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
todo!();
4
// 2. Base45 decode
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
11
12
13
14
loige 44
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
todo!()
// remove "HC1:" prefix and return remaining string
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let no_prefix = remove_prefix(cert_data);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
3
todo!();
4
// 2. Base45 decode
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn remove_prefix(data: &str) -> &str {
11
todo!()
12
// remove "HC1:" prefix and return remaining string
13
}
14
fn remove_prefix(data: &str) -> &str {
todo!()
// remove "HC1:" prefix and return remaining string
}
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
todo!();
4
// 2. Base45 decode
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
11
12
13
14
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
todo!()
// remove "HC1:" prefix and return remaining string
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
loige 44
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
if data.len() < 4 || !data.starts_with("HC1:") {
panic!("Invalid prefix"); // IRL use a Result!
}
&data[4..]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
loige 45
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
if data.len() < 4 || !data.starts_with("HC1:") {
panic!("Invalid prefix"); // IRL use a Result!
}
&data[4..]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if data.len() < 4 || !data.starts_with("HC1:") {
panic!("Invalid prefix"); // IRL use a Result!
}
&data[4..]
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
todo!();
4
// 2. Base45 decode
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn remove_prefix(data: &str) -> &str {
11
12
13
14
15
16
}
17
loige 45
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
if data.len() < 4 || !data.starts_with("HC1:") {
panic!("Invalid prefix"); // IRL use a Result!
}
&data[4..]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if data.len() < 4 || !data.starts_with("HC1:") {
panic!("Invalid prefix"); // IRL use a Result!
}
&data[4..]
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
todo!();
4
// 2. Base45 decode
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn remove_prefix(data: &str) -> &str {
11
12
13
14
15
16
}
17
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
todo!();
// 2. Base45 decode
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn remove_prefix(data: &str) -> &str {
if data.len() < 4 || !data.starts_with("HC1:") {
panic!("Invalid prefix"); // IRL use a Result!
}
&data[4..]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
loige 45
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
todo!()
// parse the string as base45 encoded and return the
// resulting raw bytes
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
loige 46
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
todo!()
// parse the string as base45 encoded and return the
// resulting raw bytes
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let decoded = decode_base45(no_prefix);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
4
todo!()
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decode_base45(data: &str) -> Vec<u8> {
11
todo!()
12
// parse the string as base45 encoded and return the
13
// resulting raw bytes
14
}
15
16
// ...
17
loige 46
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
todo!()
// parse the string as base45 encoded and return the
// resulting raw bytes
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let decoded = decode_base45(no_prefix);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
4
todo!()
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decode_base45(data: &str) -> Vec<u8> {
11
todo!()
12
// parse the string as base45 encoded and return the
13
// resulting raw bytes
14
}
15
16
// ...
17
fn decode_base45(data: &str) -> Vec<u8> {
todo!()
// parse the string as base45 encoded and return the
// resulting raw bytes
}
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
todo!()
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
11
12
13
14
15
16
// ...
17
loige 46
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
todo!()
// parse the string as base45 encoded and return the
// resulting raw bytes
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let decoded = decode_base45(no_prefix);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
4
todo!()
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decode_base45(data: &str) -> Vec<u8> {
11
todo!()
12
// parse the string as base45 encoded and return the
13
// resulting raw bytes
14
}
15
16
// ...
17
fn decode_base45(data: &str) -> Vec<u8> {
todo!()
// parse the string as base45 encoded and return the
// resulting raw bytes
}
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
todo!()
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
11
12
13
14
15
16
// ...
17
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
todo!()
// parse the string as base45 encoded and return the
// resulting raw bytes
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
loige 46
loige
cargo add base45
47
loige
cargo add base45
# Cargo.toml
# ...
[dependencies]
base45 = "3.0.0"
47
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
base45::decode(data).unwrap() // IRL use a Result!
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
loige 48
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
base45::decode(data).unwrap() // IRL use a Result!
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
base45::decode(data).unwrap() // IRL use a Result!
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
todo!()
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decode_base45(data: &str) -> Vec<u8> {
11
12
}
13
14
// ...
15
loige 48
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
base45::decode(data).unwrap() // IRL use a Result!
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
base45::decode(data).unwrap() // IRL use a Result!
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
todo!()
5
// 3. Zlib decompress
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decode_base45(data: &str) -> Vec<u8> {
11
12
}
13
14
// ...
15
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
todo!()
// 3. Zlib decompress
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decode_base45(data: &str) -> Vec<u8> {
base45::decode(data).unwrap() // IRL use a Result!
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
loige 48
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
todo!()
// decompress using zlib inflate
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
loige 49
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
todo!()
// decompress using zlib inflate
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let decompressed = decompress(decoded);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
5
todo!()
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decompress(data: Vec<u8>) -> Vec<u8> {
11
todo!()
12
// decompress using zlib inflate
13
}
14
15
// ...
16
loige 49
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
todo!()
// decompress using zlib inflate
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let decompressed = decompress(decoded);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
5
todo!()
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decompress(data: Vec<u8>) -> Vec<u8> {
11
todo!()
12
// decompress using zlib inflate
13
}
14
15
// ...
16
fn decompress(data: Vec<u8>) -> Vec<u8> {
todo!()
// decompress using zlib inflate
}
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
todo!()
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
11
12
13
14
15
// ...
16
loige 49
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
todo!()
// decompress using zlib inflate
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let decompressed = decompress(decoded);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
5
todo!()
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decompress(data: Vec<u8>) -> Vec<u8> {
11
todo!()
12
// decompress using zlib inflate
13
}
14
15
// ...
16
fn decompress(data: Vec<u8>) -> Vec<u8> {
todo!()
// decompress using zlib inflate
}
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
todo!()
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
11
12
13
14
15
// ...
16
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
todo!()
// decompress using zlib inflate
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
loige 49
loige
cargo add inflate
50
loige
cargo add inflate
# Cargo.toml
# ...
[dependencies]
base45 = "3.0.0"
inflate = "0.4.5"
50
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
inflate::inflate_bytes_zlib(data.as_slice()).unwrap()
// IRL use a Result!
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
loige 51
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
inflate::inflate_bytes_zlib(data.as_slice()).unwrap()
// IRL use a Result!
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
inflate::inflate_bytes_zlib(data.as_slice()).unwrap()
// IRL use a Result!
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
todo!()
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decompress(data: Vec<u8>) -> Vec<u8> {
11
12
13
}
14
15
// ...
16
loige 51
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
inflate::inflate_bytes_zlib(data.as_slice()).unwrap()
// IRL use a Result!
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
inflate::inflate_bytes_zlib(data.as_slice()).unwrap()
// IRL use a Result!
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
todo!()
6
// 4. Parse CWT
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn decompress(data: Vec<u8>) -> Vec<u8> {
11
12
13
}
14
15
// ...
16
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
todo!()
// 4. Parse CWT
// 5. Parse CWT Payload as CBOR
}
fn decompress(data: Vec<u8>) -> Vec<u8> {
inflate::inflate_bytes_zlib(data.as_slice()).unwrap()
// IRL use a Result!
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
loige 51
Are we on the right track?
loige
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
println!("{}", String::from_utf8_lossy(&decompressed));
}
// ...
1
2
3
4
5
6
7
8
9
10
52
Are we on the right track?
loige
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
println!("{}", String::from_utf8_lossy(&decompressed));
}
// ...
1
2
3
4
5
6
7
8
9
10
println!("{}", String::from_utf8_lossy(&decompressed));
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
6
7
}
8
9
// ...
10
52
Are we on the right track?
loige 53
Are we on the right track?
loige
We are starting to see some
readable info! 🤩 53
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
let cwt_payload = get_cwt_payload(decompressed);
todo!()
// 5. Parse CWT Payload as CBOR
}
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
todo!()
// Parse raw bytes as CBOR.
// Extract and return the raw bytes representing
// the CWT payload
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
loige 54
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
let cwt_payload = get_cwt_payload(decompressed);
todo!()
// 5. Parse CWT Payload as CBOR
}
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
todo!()
// Parse raw bytes as CBOR.
// Extract and return the raw bytes representing
// the CWT payload
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let cwt_payload = get_cwt_payload(decompressed);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
6
todo!()
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
11
todo!()
12
// Parse raw bytes as CBOR.
13
// Extract and return the raw bytes representing
14
// the CWT payload
15
}
16
17
// ...
18
loige 54
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
let cwt_payload = get_cwt_payload(decompressed);
todo!()
// 5. Parse CWT Payload as CBOR
}
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
todo!()
// Parse raw bytes as CBOR.
// Extract and return the raw bytes representing
// the CWT payload
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let cwt_payload = get_cwt_payload(decompressed);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
6
todo!()
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
11
todo!()
12
// Parse raw bytes as CBOR.
13
// Extract and return the raw bytes representing
14
// the CWT payload
15
}
16
17
// ...
18
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
todo!()
// Parse raw bytes as CBOR.
// Extract and return the raw bytes representing
// the CWT payload
}
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
let cwt_payload = get_cwt_payload(decompressed);
6
todo!()
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
11
12
13
14
15
16
17
// ...
18
loige 54
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
let cwt_payload = get_cwt_payload(decompressed);
todo!()
// 5. Parse CWT Payload as CBOR
}
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
todo!()
// Parse raw bytes as CBOR.
// Extract and return the raw bytes representing
// the CWT payload
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let cwt_payload = get_cwt_payload(decompressed);
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
6
todo!()
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
11
todo!()
12
// Parse raw bytes as CBOR.
13
// Extract and return the raw bytes representing
14
// the CWT payload
15
}
16
17
// ...
18
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
todo!()
// Parse raw bytes as CBOR.
// Extract and return the raw bytes representing
// the CWT payload
}
fn main() {
1
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
2
let no_prefix = remove_prefix(cert_data);
3
let decoded = decode_base45(no_prefix);
4
let decompressed = decompress(decoded);
5
let cwt_payload = get_cwt_payload(decompressed);
6
todo!()
7
// 5. Parse CWT Payload as CBOR
8
}
9
10
11
12
13
14
15
16
17
// ...
18
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
let cwt_payload = get_cwt_payload(decompressed);
todo!()
// 5. Parse CWT Payload as CBOR
}
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
todo!()
// Parse raw bytes as CBOR.
// Extract and return the raw bytes representing
// the CWT payload
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
loige 54
loige
cargo add ciborium
55
loige
cargo add ciborium
# Cargo.toml
# ...
[dependencies]
base45 = "3.0.0"
ciborium = "0.2.0"
inflate = "0.4.5"
55
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
let cwt_payload = get_cwt_payload(decompressed);
todo!()
// 5. Parse CWT Payload as CBOR
}
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
let parsed: Value = from_reader(data.as_slice()).unwrap();
println!("{:?}", parsed);
todo!()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
loige 56
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
let cwt_payload = get_cwt_payload(decompressed);
todo!()
// 5. Parse CWT Payload as CBOR
}
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
let parsed: Value = from_reader(data.as_slice()).unwrap();
println!("{:?}", parsed);
todo!()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
todo!()
9
// 5. Parse CWT Payload as CBOR
10
}
11
12
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
13
let parsed: Value = from_reader(data.as_slice()).unwrap();
14
println!("{:?}", parsed);
15
todo!()
16
}
17
18
// ...
19
loige 56
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
let no_prefix = remove_prefix(cert_data);
let decoded = decode_base45(no_prefix);
let decompressed = decompress(decoded);
let cwt_payload = get_cwt_payload(decompressed);
todo!()
// 5. Parse CWT Payload as CBOR
}
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
let parsed: Value = from_reader(data.as_slice()).unwrap();
println!("{:?}", parsed);
todo!()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
todo!()
9
// 5. Parse CWT Payload as CBOR
10
}
11
12
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
13
let parsed: Value = from_reader(data.as_slice()).unwrap();
14
println!("{:?}", parsed);
15
todo!()
16
}
17
18
// ...
19
let parsed: Value = from_reader(data.as_slice()).unwrap();
println!("{:?}", parsed);
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
todo!()
9
// 5. Parse CWT Payload as CBOR
10
}
11
12
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
13
14
15
todo!()
16
}
17
18
// ...
19
loige 56
57
loige
57
loige
CWT Tag (18)
57
loige
The content is an array
57
loige
57
Protected header
loige
57
Non protected header
loige
57
Payload  ✅
loige
57
Signature
loige
// ...
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
// IRL avoid .unwrap() like hell and propagate errors correctly!
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()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
loige 58
// ...
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
// IRL avoid .unwrap() like hell and propagate errors correctly!
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()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
let parsed: Value = from_reader(data.as_slice()).unwrap();
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
loige 58
// ...
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
// IRL avoid .unwrap() like hell and propagate errors correctly!
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()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
let parsed: Value = from_reader(data.as_slice()).unwrap();
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let (tag, arr) = parsed.as_tag().unwrap();
assert_eq!(tag, 18);
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
6
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
loige 58
// ...
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
// IRL avoid .unwrap() like hell and propagate errors correctly!
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()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
let parsed: Value = from_reader(data.as_slice()).unwrap();
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let (tag, arr) = parsed.as_tag().unwrap();
assert_eq!(tag, 18);
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
6
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let arr = arr.as_array().unwrap();
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
loige 58
// ...
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
// IRL avoid .unwrap() like hell and propagate errors correctly!
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()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
let parsed: Value = from_reader(data.as_slice()).unwrap();
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let (tag, arr) = parsed.as_tag().unwrap();
assert_eq!(tag, 18);
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
6
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let arr = arr.as_array().unwrap();
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let payload = arr[2].as_bytes().unwrap();
payload.clone()
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
let arr = arr.as_array().unwrap();
8
9
10
}
11
12
// ...
13
loige 58
// ...
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
// IRL avoid .unwrap() like hell and propagate errors correctly!
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()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
let parsed: Value = from_reader(data.as_slice()).unwrap();
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let (tag, arr) = parsed.as_tag().unwrap();
assert_eq!(tag, 18);
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
6
7
let arr = arr.as_array().unwrap();
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let arr = arr.as_array().unwrap();
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
8
let payload = arr[2].as_bytes().unwrap();
9
payload.clone()
10
}
11
12
// ...
13
let payload = arr[2].as_bytes().unwrap();
payload.clone()
// ...
1
2
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
3
// IRL avoid .unwrap() like hell and propagate errors correctly!
4
let parsed: Value = from_reader(data.as_slice()).unwrap();
5
let (tag, arr) = parsed.as_tag().unwrap();
6
assert_eq!(tag, 18);
7
let arr = arr.as_array().unwrap();
8
9
10
}
11
12
// ...
13
// ...
fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> {
// IRL avoid .unwrap() like hell and propagate errors correctly!
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()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
loige 58
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
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);
}
fn parse_cwt_payload(data: Vec<u8>) -> Value {
// parse the binary data as CBOR
todo!()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
loige 59
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
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);
}
fn parse_cwt_payload(data: Vec<u8>) -> Value {
// parse the binary data as CBOR
todo!()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let parsed_payload = parse_cwt_payload(cwt_payload);
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
9
}
10
11
fn parse_cwt_payload(data: Vec<u8>) -> Value {
12
// parse the binary data as CBOR
13
todo!()
14
}
15
16
// ...
17
loige 59
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
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);
}
fn parse_cwt_payload(data: Vec<u8>) -> Value {
// parse the binary data as CBOR
todo!()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let parsed_payload = parse_cwt_payload(cwt_payload);
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
9
}
10
11
fn parse_cwt_payload(data: Vec<u8>) -> Value {
12
// parse the binary data as CBOR
13
todo!()
14
}
15
16
// ...
17
fn parse_cwt_payload(data: Vec<u8>) -> Value {
// parse the binary data as CBOR
todo!()
}
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
let parsed_payload = parse_cwt_payload(cwt_payload);
9
}
10
11
12
13
14
15
16
// ...
17
loige 59
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
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!("{:#?}", parsed_payload);
}
fn parse_cwt_payload(data: Vec<u8>) -> Value {
from_reader(data.as_slice()).unwrap()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
loige 60
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
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!("{:#?}", parsed_payload);
}
fn parse_cwt_payload(data: Vec<u8>) -> Value {
from_reader(data.as_slice()).unwrap()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from_reader(data.as_slice()).unwrap()
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
let parsed_payload = parse_cwt_payload(cwt_payload);
9
println!("{:#?}", parsed_payload);
10
}
11
12
fn parse_cwt_payload(data: Vec<u8>) -> Value {
13
14
}
15
16
// ...
17
loige 60
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
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!("{:#?}", parsed_payload);
}
fn parse_cwt_payload(data: Vec<u8>) -> Value {
from_reader(data.as_slice()).unwrap()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from_reader(data.as_slice()).unwrap()
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
let parsed_payload = parse_cwt_payload(cwt_payload);
9
println!("{:#?}", parsed_payload);
10
}
11
12
fn parse_cwt_payload(data: Vec<u8>) -> Value {
13
14
}
15
16
// ...
17
println!("{:#?}", parsed_payload);
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
let parsed_payload = parse_cwt_payload(cwt_payload);
9
10
}
11
12
fn parse_cwt_payload(data: Vec<u8>) -> Value {
13
from_reader(data.as_slice()).unwrap()
14
}
15
16
// ...
17
loige 60
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
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!("{:#?}", parsed_payload);
}
fn parse_cwt_payload(data: Vec<u8>) -> Value {
from_reader(data.as_slice()).unwrap()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from_reader(data.as_slice()).unwrap()
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
let parsed_payload = parse_cwt_payload(cwt_payload);
9
println!("{:#?}", parsed_payload);
10
}
11
12
fn parse_cwt_payload(data: Vec<u8>) -> Value {
13
14
}
15
16
// ...
17
println!("{:#?}", parsed_payload);
use ciborium::{de::from_reader, value::Value};
1
2
fn main() {
3
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
4
let no_prefix = remove_prefix(cert_data);
5
let decoded = decode_base45(no_prefix);
6
let decompressed = decompress(decoded);
7
let cwt_payload = get_cwt_payload(decompressed);
8
let parsed_payload = parse_cwt_payload(cwt_payload);
9
10
}
11
12
fn parse_cwt_payload(data: Vec<u8>) -> Value {
13
from_reader(data.as_slice()).unwrap()
14
}
15
16
// ...
17
use ciborium::{de::from_reader, value::Value};
fn main() {
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
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!("{:#?}", parsed_payload);
}
fn parse_cwt_payload(data: Vec<u8>) -> Value {
from_reader(data.as_slice()).unwrap()
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
loige 60
loige 61
loige 61
Ok, let's make it more readable... 😅
loige 62
Ok, let's make it more readable... 😅
loige
cargo add serde_json
62
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
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());
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
loige 63
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
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());
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
use serde_json::to_string_pretty;
use ciborium::{de::from_reader, value::Value};
1
2
3
fn main() {
4
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
5
let no_prefix = remove_prefix(cert_data);
6
let decoded = decode_base45(no_prefix);
7
let decompressed = decompress(decoded);
8
let cwt_payload = get_cwt_payload(decompressed);
9
let parsed_payload = parse_cwt_payload(cwt_payload);
10
println!("{}", to_string_pretty(&parsed_payload).unwrap());
11
}
12
13
// ...
14
loige 63
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
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());
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
use serde_json::to_string_pretty;
use ciborium::{de::from_reader, value::Value};
1
2
3
fn main() {
4
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
5
let no_prefix = remove_prefix(cert_data);
6
let decoded = decode_base45(no_prefix);
7
let decompressed = decompress(decoded);
8
let cwt_payload = get_cwt_payload(decompressed);
9
let parsed_payload = parse_cwt_payload(cwt_payload);
10
println!("{}", to_string_pretty(&parsed_payload).unwrap());
11
}
12
13
// ...
14
println!("{}", to_string_pretty(&parsed_payload).unwrap());
use ciborium::{de::from_reader, value::Value};
1
use serde_json::to_string_pretty;
2
3
fn main() {
4
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
5
let no_prefix = remove_prefix(cert_data);
6
let decoded = decode_base45(no_prefix);
7
let decompressed = decompress(decoded);
8
let cwt_payload = get_cwt_payload(decompressed);
9
let parsed_payload = parse_cwt_payload(cwt_payload);
10
11
}
12
13
// ...
14
loige 63
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
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());
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
use serde_json::to_string_pretty;
use ciborium::{de::from_reader, value::Value};
1
2
3
fn main() {
4
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
5
let no_prefix = remove_prefix(cert_data);
6
let decoded = decode_base45(no_prefix);
7
let decompressed = decompress(decoded);
8
let cwt_payload = get_cwt_payload(decompressed);
9
let parsed_payload = parse_cwt_payload(cwt_payload);
10
println!("{}", to_string_pretty(&parsed_payload).unwrap());
11
}
12
13
// ...
14
println!("{}", to_string_pretty(&parsed_payload).unwrap());
use ciborium::{de::from_reader, value::Value};
1
use serde_json::to_string_pretty;
2
3
fn main() {
4
let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4
5
let no_prefix = remove_prefix(cert_data);
6
let decoded = decode_base45(no_prefix);
7
let decompressed = decompress(decoded);
8
let cwt_payload = get_cwt_payload(decompressed);
9
let parsed_payload = parse_cwt_payload(cwt_payload);
10
11
}
12
13
// ...
14
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
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());
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
loige 63
loige 64
loige 64
All the code:
loige.link/green-code
loige 65
A better (& more complete) implementation
as a Rust library
loige
github.com/rust-italia/dgc
66
Exercise for the viewer:
Try to validate the signature
loige 67
Exercise for the viewer:
Try to validate the signature
loige
🔑You can get the Public Key from the certificate
here: loige.link/green-examples
67
Exercise for the viewer:
Try to validate the signature
loige
🔑You can get the Public Key from the certificate
here: loige.link/green-examples
📑Here you can find more about how the CoseSign1
protocol works: loige.link/cose-sign-verif
67
Exercise for the viewer:
Try to validate the signature
loige
🔑You can get the Public Key from the certificate
here: loige.link/green-examples
📑Here you can find more about how the CoseSign1
protocol works: loige.link/cose-sign-verif
📦You could use a crate like for crypto!
ring
67
Exercise for the viewer:
Try to validate the signature
loige
🔑You can get the Public Key from the certificate
here: loige.link/green-examples
📑Here you can find more about how the CoseSign1
protocol works: loige.link/cose-sign-verif
📦You could use a crate like for crypto!
ring
(Spoiler: I implemented some of this stuff in my library!)
67
Is all this stuff legal? 😰
loige 68
Is all this stuff legal? 😰
loige
👀You can certainly look into your certificate (and the
test certificates!)
68
Is all this stuff legal? 😰
loige
👀You can certainly look into your certificate (and the
test certificates!)
🗣Looking into other people's certificate will disclose
a lot of privacy-sensitive info (thread carefully)
68
Is all this stuff legal? 😰
loige
👀You can certainly look into your certificate (and the
test certificates!)
🗣Looking into other people's certificate will disclose
a lot of privacy-sensitive info (thread carefully)
📲Building a validator app? Check your country's
regulation (especially if you need to store data!)
68
Cover Picture by on
❤  Huge thanks to for some precius review sessions and many pull requests!
❤ Thanks to , , , ,  for reviews and suggestions.
FPVmat A Unsplash
rust-italia
@gbinside @88_eugen @AlleviTommaso @npmccallum @pelger
loige
☝nodejsdp.link
loige.link/green
THANK YOU!
❤
69

Más contenido relacionado

Similar a A look inside the European Covid Green Certificate (Codemotion 2021)

Open Compliance Summit 2022 – State of the Union from Mike Dolan, SVP and GM ...
Open Compliance Summit 2022 – State of the Union from Mike Dolan, SVP and GM ...Open Compliance Summit 2022 – State of the Union from Mike Dolan, SVP and GM ...
Open Compliance Summit 2022 – State of the Union from Mike Dolan, SVP and GM ...Shane Coughlan
 
Handle your Lambdas - From event-based processing to Continuous Integration /...
Handle your Lambdas - From event-based processing to Continuous Integration /...Handle your Lambdas - From event-based processing to Continuous Integration /...
Handle your Lambdas - From event-based processing to Continuous Integration /...Sergii Khomenko
 
STARTHUB CONNECT 2018 - Blockchain Zoo_Pandu Sastrowardoyo
STARTHUB CONNECT 2018 - Blockchain Zoo_Pandu SastrowardoyoSTARTHUB CONNECT 2018 - Blockchain Zoo_Pandu Sastrowardoyo
STARTHUB CONNECT 2018 - Blockchain Zoo_Pandu SastrowardoyoAlpha Momentum Indonesia
 
DevSecOps - Colocando segurança na esteira
DevSecOps - Colocando segurança na esteiraDevSecOps - Colocando segurança na esteira
DevSecOps - Colocando segurança na esteiraDiego Gabriel Cardoso
 
6DCP Presentation 2016
6DCP Presentation 20166DCP Presentation 2016
6DCP Presentation 2016Eddie Cohen
 
Preventing Code Leaks & Other Critical Security Risks from Code
Preventing Code Leaks & Other Critical Security Risks from CodePreventing Code Leaks & Other Critical Security Risks from Code
Preventing Code Leaks & Other Critical Security Risks from CodeDevOps.com
 
Pymnts BlueFin Webinar
Pymnts BlueFin WebinarPymnts BlueFin Webinar
Pymnts BlueFin WebinarRomana Hai
 
Ceh v8-course-outline
Ceh v8-course-outlineCeh v8-course-outline
Ceh v8-course-outlineAyhan Gasanly
 
Certified ethicalhacking classroom_1382954076
Certified ethicalhacking classroom_1382954076Certified ethicalhacking classroom_1382954076
Certified ethicalhacking classroom_1382954076sunil kumar
 
Collective Authorities
Collective AuthoritiesCollective Authorities
Collective AuthoritiesIsmail Khoffi
 
Best training blockchain for colleges- https://diyblockchain.co
Best training blockchain for colleges- https://diyblockchain.coBest training blockchain for colleges- https://diyblockchain.co
Best training blockchain for colleges- https://diyblockchain.coAsif Khan
 
Diyblockchain 9jan2019 https://diyblockchain.co/
Diyblockchain 9jan2019 https://diyblockchain.co/Diyblockchain 9jan2019 https://diyblockchain.co/
Diyblockchain 9jan2019 https://diyblockchain.co/bhuvankhanna1
 
Diyblockchain -best blockchain institute for corporate training -diyblockchai...
Diyblockchain -best blockchain institute for corporate training -diyblockchai...Diyblockchain -best blockchain institute for corporate training -diyblockchai...
Diyblockchain -best blockchain institute for corporate training -diyblockchai...Asif Khan
 
BEST CRYPTOCURRENCY TRAINING
BEST CRYPTOCURRENCY TRAININGBEST CRYPTOCURRENCY TRAINING
BEST CRYPTOCURRENCY TRAININGbhuvankhanna1
 
BLOCKCHAIN AND CRYPTOCURRENCY COURSES
BLOCKCHAIN AND CRYPTOCURRENCY COURSESBLOCKCHAIN AND CRYPTOCURRENCY COURSES
BLOCKCHAIN AND CRYPTOCURRENCY COURSESbhuvankhanna1
 
Diyblockchain -best training on blockchain - https://diyblockchain.co
Diyblockchain -best training on blockchain - https://diyblockchain.coDiyblockchain -best training on blockchain - https://diyblockchain.co
Diyblockchain -best training on blockchain - https://diyblockchain.coAsif Khan
 
Best blockchain foundation course -https://diyblockchain.co
Best blockchain foundation course -https://diyblockchain.coBest blockchain foundation course -https://diyblockchain.co
Best blockchain foundation course -https://diyblockchain.coAsif Khan
 
Diyblockchain - Best blockchain certifications in Asia diyblockchain.co
Diyblockchain - Best blockchain certifications in Asia diyblockchain.coDiyblockchain - Best blockchain certifications in Asia diyblockchain.co
Diyblockchain - Best blockchain certifications in Asia diyblockchain.coAsif Khan
 

Similar a A look inside the European Covid Green Certificate (Codemotion 2021) (20)

Open Compliance Summit 2022 – State of the Union from Mike Dolan, SVP and GM ...
Open Compliance Summit 2022 – State of the Union from Mike Dolan, SVP and GM ...Open Compliance Summit 2022 – State of the Union from Mike Dolan, SVP and GM ...
Open Compliance Summit 2022 – State of the Union from Mike Dolan, SVP and GM ...
 
Handle your Lambdas - From event-based processing to Continuous Integration /...
Handle your Lambdas - From event-based processing to Continuous Integration /...Handle your Lambdas - From event-based processing to Continuous Integration /...
Handle your Lambdas - From event-based processing to Continuous Integration /...
 
STARTHUB CONNECT 2018 - Blockchain Zoo_Pandu Sastrowardoyo
STARTHUB CONNECT 2018 - Blockchain Zoo_Pandu SastrowardoyoSTARTHUB CONNECT 2018 - Blockchain Zoo_Pandu Sastrowardoyo
STARTHUB CONNECT 2018 - Blockchain Zoo_Pandu Sastrowardoyo
 
DevSecOps - Colocando segurança na esteira
DevSecOps - Colocando segurança na esteiraDevSecOps - Colocando segurança na esteira
DevSecOps - Colocando segurança na esteira
 
6DCP Presentation 2016
6DCP Presentation 20166DCP Presentation 2016
6DCP Presentation 2016
 
Blockchain v Cryptocurrency: Talk for BridgeSF
Blockchain v Cryptocurrency: Talk for BridgeSF Blockchain v Cryptocurrency: Talk for BridgeSF
Blockchain v Cryptocurrency: Talk for BridgeSF
 
Preventing Code Leaks & Other Critical Security Risks from Code
Preventing Code Leaks & Other Critical Security Risks from CodePreventing Code Leaks & Other Critical Security Risks from Code
Preventing Code Leaks & Other Critical Security Risks from Code
 
Secure pl-sql-coding
Secure pl-sql-codingSecure pl-sql-coding
Secure pl-sql-coding
 
Pymnts BlueFin Webinar
Pymnts BlueFin WebinarPymnts BlueFin Webinar
Pymnts BlueFin Webinar
 
Ceh v8-course-outline
Ceh v8-course-outlineCeh v8-course-outline
Ceh v8-course-outline
 
Certified ethicalhacking classroom_1382954076
Certified ethicalhacking classroom_1382954076Certified ethicalhacking classroom_1382954076
Certified ethicalhacking classroom_1382954076
 
Collective Authorities
Collective AuthoritiesCollective Authorities
Collective Authorities
 
Best training blockchain for colleges- https://diyblockchain.co
Best training blockchain for colleges- https://diyblockchain.coBest training blockchain for colleges- https://diyblockchain.co
Best training blockchain for colleges- https://diyblockchain.co
 
Diyblockchain 9jan2019 https://diyblockchain.co/
Diyblockchain 9jan2019 https://diyblockchain.co/Diyblockchain 9jan2019 https://diyblockchain.co/
Diyblockchain 9jan2019 https://diyblockchain.co/
 
Diyblockchain -best blockchain institute for corporate training -diyblockchai...
Diyblockchain -best blockchain institute for corporate training -diyblockchai...Diyblockchain -best blockchain institute for corporate training -diyblockchai...
Diyblockchain -best blockchain institute for corporate training -diyblockchai...
 
BEST CRYPTOCURRENCY TRAINING
BEST CRYPTOCURRENCY TRAININGBEST CRYPTOCURRENCY TRAINING
BEST CRYPTOCURRENCY TRAINING
 
BLOCKCHAIN AND CRYPTOCURRENCY COURSES
BLOCKCHAIN AND CRYPTOCURRENCY COURSESBLOCKCHAIN AND CRYPTOCURRENCY COURSES
BLOCKCHAIN AND CRYPTOCURRENCY COURSES
 
Diyblockchain -best training on blockchain - https://diyblockchain.co
Diyblockchain -best training on blockchain - https://diyblockchain.coDiyblockchain -best training on blockchain - https://diyblockchain.co
Diyblockchain -best training on blockchain - https://diyblockchain.co
 
Best blockchain foundation course -https://diyblockchain.co
Best blockchain foundation course -https://diyblockchain.coBest blockchain foundation course -https://diyblockchain.co
Best blockchain foundation course -https://diyblockchain.co
 
Diyblockchain - Best blockchain certifications in Asia diyblockchain.co
Diyblockchain - Best blockchain certifications in Asia diyblockchain.coDiyblockchain - Best blockchain certifications in Asia diyblockchain.co
Diyblockchain - Best blockchain certifications in Asia diyblockchain.co
 

Más de Luciano Mammino

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSLuciano Mammino
 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...Luciano Mammino
 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoLuciano Mammino
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperLuciano Mammino
 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Luciano Mammino
 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsLuciano Mammino
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance ComputingLuciano Mammino
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance ComputingLuciano Mammino
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022Luciano Mammino
 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableLuciano Mammino
 
Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Luciano Mammino
 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinLuciano Mammino
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaLuciano Mammino
 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made SimpleLuciano Mammino
 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessLuciano Mammino
 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Luciano Mammino
 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Luciano Mammino
 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3Luciano Mammino
 

Más de Luciano Mammino (20)

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJS
 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiper
 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!
 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLs
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & Airtable
 
Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀
 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust Dublin
 
Monoliths to the cloud!
Monoliths to the cloud!Monoliths to the cloud!
Monoliths to the cloud!
 
The senior dev
The senior devThe senior dev
The senior dev
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community Vijayawada
 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made Simple
 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti Serverless
 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021
 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3
 

Último

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 

Último (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 

A look inside the European Covid Green Certificate (Codemotion 2021)

  • 1. A look inside the European Covid Green Certificate Luciano Mammino ( ) @loige 2021-12-01 loige.link/green 1
  • 3. Let me introduce myself first... 3
  • 4. Let me introduce myself first... 👋I'm Luciano ( 🍕🍝 ) 3
  • 5. Let me introduce myself first... 👋I'm Luciano ( 🍕🍝 ) Senior Architect @ fourTheorem (Dublin ) 3
  • 6. Let me introduce myself first... 👋I'm Luciano ( 🍕🍝 ) Senior Architect @ fourTheorem (Dublin ) nodejsdp.link 📔Co-Author of Node.js Design Patterns  👉 3
  • 7. Let me introduce myself first... 👋I'm Luciano ( 🍕🍝 ) Senior Architect @ fourTheorem (Dublin ) nodejsdp.link 📔Co-Author of Node.js Design Patterns  👉 Let's connect!   (blog)   (twitter)   (twitch)   (github) loige.co @loige loige lmammino 3
  • 8. We are business focused technologists that deliver.  |  | Accelerated Serverless AI as a Service Platform Modernisation We are hiring: do you want to ? work with us loige 4
  • 10. Disclaimers loige 🤓I am not involved with the DGC working group   5
  • 11. Disclaimers loige 🤓I am not involved with the DGC working group   😢COVID has been tough on everyone,       we'll try to focus only on the tech here! 5
  • 13. Agenda + Goals loige 1. Needs and principles 2. 🗝Cryptographic model 3. 📦The data 4. 🧅Layers of encoding 5. 🛠Decoding in Rust 6
  • 14. Agenda + Goals loige 1. Needs and principles 2. 🗝Cryptographic model 3. 📦The data 4. 🧅Layers of encoding 5. 🛠Decoding in Rust 🤨Learn some cool technologies 🧐Learn a tiny bit of Rust 🤓Be nerdy and have fun! 6
  • 15. The need for a digital certificate in the COVID age loige 7
  • 16. The need for a digital certificate in the COVID age loige 8
  • 17. The need for a digital certificate in the COVID age loige 😷We need a system to quickly provide a proof against COVID       (Vaccination, negative test, proof of recovery)  8
  • 18. The need for a digital certificate in the COVID age loige 😷We need a system to quickly provide a proof against COVID       (Vaccination, negative test, proof of recovery)  It needs to be personal, easy to carry around (digital),        easy to issue and to validate 8
  • 19. The need for a digital certificate in the COVID age loige 😷We need a system to quickly provide a proof against COVID       (Vaccination, negative test, proof of recovery)  It needs to be personal, easy to carry around (digital),        easy to issue and to validate 🌎It needs to be secure against forgery and work across countries 8
  • 20. The EU Covid Green Pass a.k.a.  Electronic Health Certificates (HCERT)   loige.link/hcert-spec loige 9
  • 21. Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige 10
  • 22. Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige ✍Signed data with machine readable content 10
  • 23. Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige ✍Signed data with machine readable content 📃Use compact encoding 10
  • 24. Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige ✍Signed data with machine readable content 📃Use compact encoding 🤲Based on open standards 10
  • 26. Asymmetric cryptographic signatures loige 🤫Private Key 101010101000101010010... 11
  • 27. Asymmetric cryptographic signatures loige 🤫Private Key 📢Public Key 101010101000101010010... 0101010101010101010101... 11
  • 28. Asymmetric cryptographic signatures loige 🤫Private Key 📢Public Key 🔗 101010101000101010010... 0101010101010101010101... 11
  • 29. Asymmetric cryptographic signatures loige 🤫Private Key 📢Public Key 101010101000101010010... 0101010101010101010101... 12
  • 30. Asymmetric cryptographic signatures loige 🤫Private Key 📢Public Key 101010101000101010010... 0101010101010101010101... 12
  • 31. Asymmetric cryptographic signatures loige 🤫Private Key 📢Public Key 101010101000101010010... 0101010101010101010101... The owner of the private key signs the document 12
  • 32. Asymmetric cryptographic signatures loige 🤫Private Key 📢Public Key 101010101000101010010... 0101010101010101010101... The owner of the private key signs the document 12
  • 33. Asymmetric cryptographic signatures loige 🤫Private Key 📢Public Key 101010101000101010010... 0101010101010101010101... The owner of the private key signs the document Anyone can validate the signature using the public key 12
  • 34. Asymmetric cryptographic signatures loige 🤫Private Key 📢Public Key 101010101000101010010... 0101010101010101010101... The owner of the private key signs the document Anyone can validate the signature using the public key 12
  • 35. What's inside a certificate? loige 13
  • 36. What's inside a certificate? loige 13
  • 37. What's inside a certificate? loige Cryptographic header (Key Id, Algorithm) 13
  • 38. What's inside a certificate? loige DGC container Cryptographic header (Key Id, Algorithm) 13
  • 39. What's inside a certificate? loige DGC container Cryptographic header (Key Id, Algorithm) Cryptographic Signature 13
  • 40. What's inside a certificate? loige DGC container Cryptographic header (Key Id, Algorithm) Cryptographic Signature Header (Issuer, Issue date, expiry date) 13
  • 41. What's inside a certificate? loige DGC container Cryptographic header (Key Id, Algorithm) Cryptographic Signature Header (Issuer, Issue date, expiry date) 13 Certificates list Personal data (name, surname, DoB)
  • 42. What's inside a certificate? loige DGC container Cryptographic header (Key Id, Algorithm) Cryptographic Signature Header (Issuer, Issue date, expiry date) 13 Certificates list vaccine, test, or recovery data Personal data (name, surname, DoB)
  • 45. { "1": "DK", "4": 1625054000, "6": 1622462000, "-260": { "ver":"1.0.0", "nam":{ "fn":"Klaus", "fnt":"KLAUS", "gn":"Jørgensen", "gnt":"JOERGENSEN" }, "dob":"1983-01-06", "v":[ { "tg":"840539006", "vp":"1119349007", "mp":"EU/1/20/1528", "ma":"ORG-100030215", "dn":2, "sd":2, "dt":"2021-05-03", "co":"DK", "is":"Danish Health Data Authority", "ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A" } ] } } An example loige loige.link/green-examples 15
  • 46. { "1": "DK", "4": 1625054000, "6": 1622462000, "-260": { "ver":"1.0.0", "nam":{ "fn":"Klaus", "fnt":"KLAUS", "gn":"Jørgensen", "gnt":"JOERGENSEN" }, "dob":"1983-01-06", "v":[ { "tg":"840539006", "vp":"1119349007", "mp":"EU/1/20/1528", "ma":"ORG-100030215", "dn":2, "sd":2, "dt":"2021-05-03", "co":"DK", "is":"Danish Health Data Authority", "ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A" } ] } } An example loige loige.link/green-examples DGC Header 15
  • 47. { "1": "DK", "4": 1625054000, "6": 1622462000, "-260": { "ver":"1.0.0", "nam":{ "fn":"Klaus", "fnt":"KLAUS", "gn":"Jørgensen", "gnt":"JOERGENSEN" }, "dob":"1983-01-06", "v":[ { "tg":"840539006", "vp":"1119349007", "mp":"EU/1/20/1528", "ma":"ORG-100030215", "dn":2, "sd":2, "dt":"2021-05-03", "co":"DK", "is":"Danish Health Data Authority", "ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A" } ] } } An example loige loige.link/green-examples Personal info DGC Header 15
  • 48. { "1": "DK", "4": 1625054000, "6": 1622462000, "-260": { "ver":"1.0.0", "nam":{ "fn":"Klaus", "fnt":"KLAUS", "gn":"Jørgensen", "gnt":"JOERGENSEN" }, "dob":"1983-01-06", "v":[ { "tg":"840539006", "vp":"1119349007", "mp":"EU/1/20/1528", "ma":"ORG-100030215", "dn":2, "sd":2, "dt":"2021-05-03", "co":"DK", "is":"Danish Health Data Authority", "ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A" } ] } } An example loige loige.link/green-examples Personal info Vaccine info DGC Header 15
  • 52. Layered encoding loige QRCODE ASCII mode Prefix + Base45 encoding Zlib compression 16 🧅
  • 53. Layered encoding loige QRCODE ASCII mode Prefix + Base45 encoding Zlib compression CWT signed data (COSE) 16 🧅
  • 54. Layered encoding loige QRCODE ASCII mode Prefix + Base45 encoding Zlib compression CWT signed data (COSE) CBOR document 16 🧅
  • 61. loige Allows to encode binary data in text format (ASCII) Base45 19
  • 62. loige Allows to encode binary data in text format (ASCII) Like Base64, but it uses 45 characters instead: Base45 19
  • 63. loige Allows to encode binary data in text format (ASCII) Like Base64, but it uses 45 characters instead: loige.link/base45-explained Base45 19
  • 65. Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001 00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 Some binary data 20
  • 66. Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001 00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 Some binary data 20
  • 67. Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001 00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 UTF8 (17 bytes) I got my shots 💉 Some binary data 20
  • 68. Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001 00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 UTF8 (17 bytes) I got my shots 💉 Hex (38 bytes) 49 20 67 6f 74 20 6d 79 20 73 68 6f 74 73 20 f0 9f 92 89 Some binary data 20
  • 69. Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001 00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 UTF8 (17 bytes) I got my shots 💉 Hex (38 bytes) 49 20 67 6f 74 20 6d 79 20 73 68 6f 74 73 20 f0 9f 92 89 Base64 (28 bytes) SSBnb3QgbXkgc2hvdHMg8J+SiQ== Some binary data 20
  • 70. Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001 00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 UTF8 (17 bytes) I got my shots 💉 Hex (38 bytes) 49 20 67 6f 74 20 6d 79 20 73 68 6f 74 73 20 f0 9f 92 89 Base64 (28 bytes) SSBnb3QgbXkgc2hvdHMg8J+SiQ== Base45 (29 bytes) 0B9J3DSUEZ$DR4459DLWEH74Z7K23 Some binary data 20
  • 71. loige loige.link/base45-rfc "A QR-code is used to encode text as a graphical image. [...] QR-codes cannot be used to encode arbitrary binary data directly.  [...] Compared to already established Base64, Base32 and Base16 encoding schemes [...], the Base45 scheme described in this document offer a more compact QR-code encoding" Base45 21
  • 77. Zlib compression loige "zlib is designed to be a free, general-purpose, legally unencumbered -- that is, not covered by any patents -- lossless data-compression library for use on virtually any computer hardware and operating system" zlib.net 24
  • 81. Zlib compression loige Zlib inflate Compressed binary data Decompressed binary data 25
  • 84. Zlib compression loige 👀We start to see some "readable" information! 26
  • 85. COSE / CWT loige CBOR Object Signing and Encryption / CBOR Web Token 27
  • 86. CBOR !? 🤔 loige But wait, what the heck is ✋ 28
  • 87. CBOR loige TLDR; Like JSON but in binary! loige.link/cbor-rfc 29
  • 88. JSON loige A schema-less data format where a value can be: Null Boolean Number String Array Object null true -17.34 "A programmer walks into a bar..." ["foo", 1.23, null, false, [22]] {"foo": "bar", "manyvals": [1,2,3], "nested": {}} 30
  • 89. CBOR loige A schema-less binary data format where a value can be: Null Boolean Number String Text Array Object Map F6 F5 fbc031570a3d70a3d7 7820412070726f6772616d6d65722077616c6b7320696e746f2061206261722e2e2e 8563666f6ffb3ff3ae147ae147aef6f48116 a363666f6f63626172686d616e7976616c7383010203666e6573746564a0 31
  • 90. CBOR loige It also supports: Byte String (a sequence of raw bytes) Tags (annotations that allow to create new types) 32
  • 91. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 33
  • 92. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { } 33
  • 93. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": } 33
  • 94. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", } 33
  • 95. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": } 33
  • 96. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], 33
  • 97. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], 1, 33
  • 98. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], 1, 2, 33
  • 99. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], 1, 2, 3 33
  • 100. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], "nested": 1, 2, 3 33
  • 101. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], "nested": {} 1, 2, 3 33
  • 102. COSE / CWT loige CBOR Object Signing and Encryption / CBOR Web Token ok... again 😅 34
  • 103. COSE loige CBOR Object Signing and Encryption 35
  • 104. COSE loige CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE 35
  • 105. COSE loige CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE Encrypted data 35
  • 106. COSE loige CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE Encrypted data Cryptographic signed data 35
  • 107. COSE loige CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE Encrypted data Cryptographic signed data MACed data 35
  • 108. COSE loige loige.link/cose-rfc CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE Encrypted data Cryptographic signed data MACed data 35
  • 110. CWT loige Like but for CBOR JWT CBOR Web Token 36
  • 111. CWT loige Like but for CBOR JWT Defines a protocol for transferring claims between parties CBOR Web Token 36
  • 112. CWT loige Like but for CBOR JWT Defines a protocol for transferring claims between parties CBOR Web Token Claims are digitally signed for authenticity 36
  • 113. CWT loige Like but for CBOR JWT loige.link/cwt-rfc Defines a protocol for transferring claims between parties CBOR Web Token Claims are digitally signed for authenticity 36
  • 115. CWT loige A CWT is made of 4 parts: CBOR Web Token 37
  • 116. CWT loige A CWT is made of 4 parts: Protected header CBOR Web Token 37
  • 117. CWT loige A CWT is made of 4 parts: Protected header CBOR Web Token Non protected header 37
  • 118. CWT loige A CWT is made of 4 parts: Protected header CBOR Web Token Non protected header Payload 37
  • 119. CWT loige A CWT is made of 4 parts: Protected header CBOR Web Token Non protected header Payload Signature 37
  • 120. CWT loige A CWT is encoded as a (tagged) CBOR array with 4 values: Protected header (binary string) CBOR Web Token Non protected header (map) Payload (binary string) Signature (binary string) 38
  • 129. Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0)
  • 130. Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0)
  • 131. Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0) Payload Binary String
  • 132. Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0) Payload Binary String
  • 133. Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0) Payload Binary String Signature Binary String
  • 136. loige CWT payload Binary String follows (CBOR Encoded) 40
  • 137. loige CWT payload { "1": "DK", "4": 1625054000, "6": 1622462000, "-260": { "ver":"1.0.0", "nam":{ "fn":"Klaus", "fnt":"KLAUS", "gn":"Jørgensen", "gnt":"JOERGENSEN" }, "dob":"1983-01-06", "v":[ { "tg":"840539006", "vp":"1119349007", "mp":"EU/1/20/1528", "ma":"ORG-100030215", "dn":2, "sd":2, "dt":"2021-05-03", "co":"DK", "is":"Danish Health Data Authority", "ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A" } ] } } Binary String follows (CBOR Encoded) CBOR decode     (to JSON) 40
  • 138. loige CWT payload { "1": "DK", "4": 1625054000, "6": 1622462000, "-260": { "ver":"1.0.0", "nam":{ "fn":"Klaus", "fnt":"KLAUS", "gn":"Jørgensen", "gnt":"JOERGENSEN" }, "dob":"1983-01-06", "v":[ { "tg":"840539006", "vp":"1119349007", "mp":"EU/1/20/1528", "ma":"ORG-100030215", "dn":2, "sd":2, "dt":"2021-05-03", "co":"DK", "is":"Danish Health Data Authority", "ci":"URN:UVCI:01:DK:B986830007345F99AE898FB82C6C61F2#A" } ] } } Binary String follows (CBOR Encoded) CBOR decode     (to JSON) 40
  • 139. How to decode - quick recap loige 41
  • 140. How to decode - quick recap loige 1. Remove "HC1:" prefix 41
  • 141. How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 41
  • 142. How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 41
  • 143. How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 4. Parse CWT 41
  • 144. How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 4. Parse CWT 5. Parse CWT Payload as CBOR 41
  • 145. How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 4. Parse CWT 5. Parse CWT Payload as CBOR 6. Party hard! 🥳 41
  • 146. How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 4. Parse CWT 5. Parse CWT Payload as CBOR 6. Party hard! 🥳 41
  • 147. How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 4. Parse CWT 5. Parse CWT Payload as CBOR 6. Party hard! 🥳 Hey, let's implement this... 41
  • 148. How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 4. Parse CWT 5. Parse CWT Payload as CBOR 6. Party hard! 🥳 Hey, let's implement this... in Rust! 41
  • 150. // src/main.rs fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 todo!() // 1. Remove "HC1:" prefix // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } 1 2 3 4 5 6 7 8 9 10 11 loige 43
  • 151. // src/main.rs fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 todo!() // 1. Remove "HC1:" prefix // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } 1 2 3 4 5 6 7 8 9 10 11 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 // src/main.rs 1 2 fn main() { 3 4 todo!() 5 // 1. Remove "HC1:" prefix 6 // 2. Base45 decode 7 // 3. Zlib decompress 8 // 4. Parse CWT 9 // 5. Parse CWT Payload as CBOR 10 } 11 loige 43
  • 152. // src/main.rs fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 todo!() // 1. Remove "HC1:" prefix // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } 1 2 3 4 5 6 7 8 9 10 11 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 // src/main.rs 1 2 fn main() { 3 4 todo!() 5 // 1. Remove "HC1:" prefix 6 // 2. Base45 decode 7 // 3. Zlib decompress 8 // 4. Parse CWT 9 // 5. Parse CWT Payload as CBOR 10 } 11 todo!() // 1. Remove "HC1:" prefix // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR // src/main.rs 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 5 6 7 8 9 10 } 11 loige 43
  • 153. // src/main.rs fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 todo!() // 1. Remove "HC1:" prefix // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } 1 2 3 4 5 6 7 8 9 10 11 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 // src/main.rs 1 2 fn main() { 3 4 todo!() 5 // 1. Remove "HC1:" prefix 6 // 2. Base45 decode 7 // 3. Zlib decompress 8 // 4. Parse CWT 9 // 5. Parse CWT Payload as CBOR 10 } 11 todo!() // 1. Remove "HC1:" prefix // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR // src/main.rs 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 5 6 7 8 9 10 } 11 // src/main.rs fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 todo!() // 1. Remove "HC1:" prefix // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } 1 2 3 4 5 6 7 8 9 10 11 loige 43
  • 154. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { todo!() // remove "HC1:" prefix and return remaining string } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 loige 44
  • 155. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { todo!() // remove "HC1:" prefix and return remaining string } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 let no_prefix = remove_prefix(cert_data); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 3 todo!(); 4 // 2. Base45 decode 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn remove_prefix(data: &str) -> &str { 11 todo!() 12 // remove "HC1:" prefix and return remaining string 13 } 14 loige 44
  • 156. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { todo!() // remove "HC1:" prefix and return remaining string } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 let no_prefix = remove_prefix(cert_data); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 3 todo!(); 4 // 2. Base45 decode 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn remove_prefix(data: &str) -> &str { 11 todo!() 12 // remove "HC1:" prefix and return remaining string 13 } 14 fn remove_prefix(data: &str) -> &str { todo!() // remove "HC1:" prefix and return remaining string } fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 todo!(); 4 // 2. Base45 decode 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 11 12 13 14 loige 44
  • 157. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { todo!() // remove "HC1:" prefix and return remaining string } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 let no_prefix = remove_prefix(cert_data); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 3 todo!(); 4 // 2. Base45 decode 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn remove_prefix(data: &str) -> &str { 11 todo!() 12 // remove "HC1:" prefix and return remaining string 13 } 14 fn remove_prefix(data: &str) -> &str { todo!() // remove "HC1:" prefix and return remaining string } fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 todo!(); 4 // 2. Base45 decode 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 11 12 13 14 fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { todo!() // remove "HC1:" prefix and return remaining string } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 loige 44
  • 158. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { if data.len() < 4 || !data.starts_with("HC1:") { panic!("Invalid prefix"); // IRL use a Result! } &data[4..] } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 loige 45
  • 159. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { if data.len() < 4 || !data.starts_with("HC1:") { panic!("Invalid prefix"); // IRL use a Result! } &data[4..] } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 if data.len() < 4 || !data.starts_with("HC1:") { panic!("Invalid prefix"); // IRL use a Result! } &data[4..] fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 todo!(); 4 // 2. Base45 decode 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn remove_prefix(data: &str) -> &str { 11 12 13 14 15 16 } 17 loige 45
  • 160. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { if data.len() < 4 || !data.starts_with("HC1:") { panic!("Invalid prefix"); // IRL use a Result! } &data[4..] } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 if data.len() < 4 || !data.starts_with("HC1:") { panic!("Invalid prefix"); // IRL use a Result! } &data[4..] fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 todo!(); 4 // 2. Base45 decode 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn remove_prefix(data: &str) -> &str { 11 12 13 14 15 16 } 17 fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); todo!(); // 2. Base45 decode // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn remove_prefix(data: &str) -> &str { if data.len() < 4 || !data.starts_with("HC1:") { panic!("Invalid prefix"); // IRL use a Result! } &data[4..] } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 loige 45
  • 161. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { todo!() // parse the string as base45 encoded and return the // resulting raw bytes } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 loige 46
  • 162. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { todo!() // parse the string as base45 encoded and return the // resulting raw bytes } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let decoded = decode_base45(no_prefix); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 4 todo!() 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decode_base45(data: &str) -> Vec<u8> { 11 todo!() 12 // parse the string as base45 encoded and return the 13 // resulting raw bytes 14 } 15 16 // ... 17 loige 46
  • 163. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { todo!() // parse the string as base45 encoded and return the // resulting raw bytes } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let decoded = decode_base45(no_prefix); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 4 todo!() 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decode_base45(data: &str) -> Vec<u8> { 11 todo!() 12 // parse the string as base45 encoded and return the 13 // resulting raw bytes 14 } 15 16 // ... 17 fn decode_base45(data: &str) -> Vec<u8> { todo!() // parse the string as base45 encoded and return the // resulting raw bytes } fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 todo!() 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 11 12 13 14 15 16 // ... 17 loige 46
  • 164. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { todo!() // parse the string as base45 encoded and return the // resulting raw bytes } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let decoded = decode_base45(no_prefix); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 4 todo!() 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decode_base45(data: &str) -> Vec<u8> { 11 todo!() 12 // parse the string as base45 encoded and return the 13 // resulting raw bytes 14 } 15 16 // ... 17 fn decode_base45(data: &str) -> Vec<u8> { todo!() // parse the string as base45 encoded and return the // resulting raw bytes } fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 todo!() 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 11 12 13 14 15 16 // ... 17 fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { todo!() // parse the string as base45 encoded and return the // resulting raw bytes } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 loige 46
  • 166. loige cargo add base45 # Cargo.toml # ... [dependencies] base45 = "3.0.0" 47
  • 167. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { base45::decode(data).unwrap() // IRL use a Result! } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 loige 48
  • 168. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { base45::decode(data).unwrap() // IRL use a Result! } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 base45::decode(data).unwrap() // IRL use a Result! fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 todo!() 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decode_base45(data: &str) -> Vec<u8> { 11 12 } 13 14 // ... 15 loige 48
  • 169. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { base45::decode(data).unwrap() // IRL use a Result! } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 base45::decode(data).unwrap() // IRL use a Result! fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 todo!() 5 // 3. Zlib decompress 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decode_base45(data: &str) -> Vec<u8> { 11 12 } 13 14 // ... 15 fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); todo!() // 3. Zlib decompress // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decode_base45(data: &str) -> Vec<u8> { base45::decode(data).unwrap() // IRL use a Result! } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 loige 48
  • 170. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { todo!() // decompress using zlib inflate } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 loige 49
  • 171. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { todo!() // decompress using zlib inflate } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let decompressed = decompress(decoded); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 5 todo!() 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decompress(data: Vec<u8>) -> Vec<u8> { 11 todo!() 12 // decompress using zlib inflate 13 } 14 15 // ... 16 loige 49
  • 172. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { todo!() // decompress using zlib inflate } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let decompressed = decompress(decoded); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 5 todo!() 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decompress(data: Vec<u8>) -> Vec<u8> { 11 todo!() 12 // decompress using zlib inflate 13 } 14 15 // ... 16 fn decompress(data: Vec<u8>) -> Vec<u8> { todo!() // decompress using zlib inflate } fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 todo!() 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 11 12 13 14 15 // ... 16 loige 49
  • 173. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { todo!() // decompress using zlib inflate } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let decompressed = decompress(decoded); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 5 todo!() 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decompress(data: Vec<u8>) -> Vec<u8> { 11 todo!() 12 // decompress using zlib inflate 13 } 14 15 // ... 16 fn decompress(data: Vec<u8>) -> Vec<u8> { todo!() // decompress using zlib inflate } fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 todo!() 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 11 12 13 14 15 // ... 16 fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { todo!() // decompress using zlib inflate } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 loige 49
  • 175. loige cargo add inflate # Cargo.toml # ... [dependencies] base45 = "3.0.0" inflate = "0.4.5" 50
  • 176. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { inflate::inflate_bytes_zlib(data.as_slice()).unwrap() // IRL use a Result! } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 loige 51
  • 177. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { inflate::inflate_bytes_zlib(data.as_slice()).unwrap() // IRL use a Result! } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 inflate::inflate_bytes_zlib(data.as_slice()).unwrap() // IRL use a Result! fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 todo!() 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decompress(data: Vec<u8>) -> Vec<u8> { 11 12 13 } 14 15 // ... 16 loige 51
  • 178. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { inflate::inflate_bytes_zlib(data.as_slice()).unwrap() // IRL use a Result! } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 inflate::inflate_bytes_zlib(data.as_slice()).unwrap() // IRL use a Result! fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 todo!() 6 // 4. Parse CWT 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn decompress(data: Vec<u8>) -> Vec<u8> { 11 12 13 } 14 15 // ... 16 fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); todo!() // 4. Parse CWT // 5. Parse CWT Payload as CBOR } fn decompress(data: Vec<u8>) -> Vec<u8> { inflate::inflate_bytes_zlib(data.as_slice()).unwrap() // IRL use a Result! } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 loige 51
  • 179. Are we on the right track? loige fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); println!("{}", String::from_utf8_lossy(&decompressed)); } // ... 1 2 3 4 5 6 7 8 9 10 52
  • 180. Are we on the right track? loige fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); println!("{}", String::from_utf8_lossy(&decompressed)); } // ... 1 2 3 4 5 6 7 8 9 10 println!("{}", String::from_utf8_lossy(&decompressed)); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 6 7 } 8 9 // ... 10 52
  • 181. Are we on the right track? loige 53
  • 182. Are we on the right track? loige We are starting to see some readable info! 🤩 53
  • 183. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); let cwt_payload = get_cwt_payload(decompressed); todo!() // 5. Parse CWT Payload as CBOR } fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { todo!() // Parse raw bytes as CBOR. // Extract and return the raw bytes representing // the CWT payload } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 loige 54
  • 184. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); let cwt_payload = get_cwt_payload(decompressed); todo!() // 5. Parse CWT Payload as CBOR } fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { todo!() // Parse raw bytes as CBOR. // Extract and return the raw bytes representing // the CWT payload } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let cwt_payload = get_cwt_payload(decompressed); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 6 todo!() 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 11 todo!() 12 // Parse raw bytes as CBOR. 13 // Extract and return the raw bytes representing 14 // the CWT payload 15 } 16 17 // ... 18 loige 54
  • 185. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); let cwt_payload = get_cwt_payload(decompressed); todo!() // 5. Parse CWT Payload as CBOR } fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { todo!() // Parse raw bytes as CBOR. // Extract and return the raw bytes representing // the CWT payload } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let cwt_payload = get_cwt_payload(decompressed); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 6 todo!() 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 11 todo!() 12 // Parse raw bytes as CBOR. 13 // Extract and return the raw bytes representing 14 // the CWT payload 15 } 16 17 // ... 18 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { todo!() // Parse raw bytes as CBOR. // Extract and return the raw bytes representing // the CWT payload } fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 let cwt_payload = get_cwt_payload(decompressed); 6 todo!() 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 11 12 13 14 15 16 17 // ... 18 loige 54
  • 186. fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); let cwt_payload = get_cwt_payload(decompressed); todo!() // 5. Parse CWT Payload as CBOR } fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { todo!() // Parse raw bytes as CBOR. // Extract and return the raw bytes representing // the CWT payload } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let cwt_payload = get_cwt_payload(decompressed); fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 6 todo!() 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 11 todo!() 12 // Parse raw bytes as CBOR. 13 // Extract and return the raw bytes representing 14 // the CWT payload 15 } 16 17 // ... 18 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { todo!() // Parse raw bytes as CBOR. // Extract and return the raw bytes representing // the CWT payload } fn main() { 1 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 2 let no_prefix = remove_prefix(cert_data); 3 let decoded = decode_base45(no_prefix); 4 let decompressed = decompress(decoded); 5 let cwt_payload = get_cwt_payload(decompressed); 6 todo!() 7 // 5. Parse CWT Payload as CBOR 8 } 9 10 11 12 13 14 15 16 17 // ... 18 fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); let cwt_payload = get_cwt_payload(decompressed); todo!() // 5. Parse CWT Payload as CBOR } fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { todo!() // Parse raw bytes as CBOR. // Extract and return the raw bytes representing // the CWT payload } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 loige 54
  • 188. loige cargo add ciborium # Cargo.toml # ... [dependencies] base45 = "3.0.0" ciborium = "0.2.0" inflate = "0.4.5" 55
  • 189. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); let cwt_payload = get_cwt_payload(decompressed); todo!() // 5. Parse CWT Payload as CBOR } fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { let parsed: Value = from_reader(data.as_slice()).unwrap(); println!("{:?}", parsed); todo!() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 loige 56
  • 190. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); let cwt_payload = get_cwt_payload(decompressed); todo!() // 5. Parse CWT Payload as CBOR } fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { let parsed: Value = from_reader(data.as_slice()).unwrap(); println!("{:?}", parsed); todo!() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 todo!() 9 // 5. Parse CWT Payload as CBOR 10 } 11 12 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 13 let parsed: Value = from_reader(data.as_slice()).unwrap(); 14 println!("{:?}", parsed); 15 todo!() 16 } 17 18 // ... 19 loige 56
  • 191. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 let no_prefix = remove_prefix(cert_data); let decoded = decode_base45(no_prefix); let decompressed = decompress(decoded); let cwt_payload = get_cwt_payload(decompressed); todo!() // 5. Parse CWT Payload as CBOR } fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { let parsed: Value = from_reader(data.as_slice()).unwrap(); println!("{:?}", parsed); todo!() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 todo!() 9 // 5. Parse CWT Payload as CBOR 10 } 11 12 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 13 let parsed: Value = from_reader(data.as_slice()).unwrap(); 14 println!("{:?}", parsed); 15 todo!() 16 } 17 18 // ... 19 let parsed: Value = from_reader(data.as_slice()).unwrap(); println!("{:?}", parsed); use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 todo!() 9 // 5. Parse CWT Payload as CBOR 10 } 11 12 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 13 14 15 todo!() 16 } 17 18 // ... 19 loige 56
  • 195. The content is an array 57 loige
  • 200. // ... fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { // IRL avoid .unwrap() like hell and propagate errors correctly! 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() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 loige 58
  • 201. // ... fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { // IRL avoid .unwrap() like hell and propagate errors correctly! 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() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 let parsed: Value = from_reader(data.as_slice()).unwrap(); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 loige 58
  • 202. // ... fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { // IRL avoid .unwrap() like hell and propagate errors correctly! 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() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 let parsed: Value = from_reader(data.as_slice()).unwrap(); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let (tag, arr) = parsed.as_tag().unwrap(); assert_eq!(tag, 18); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 6 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 loige 58
  • 203. // ... fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { // IRL avoid .unwrap() like hell and propagate errors correctly! 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() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 let parsed: Value = from_reader(data.as_slice()).unwrap(); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let (tag, arr) = parsed.as_tag().unwrap(); assert_eq!(tag, 18); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 6 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let arr = arr.as_array().unwrap(); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 loige 58
  • 204. // ... fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { // IRL avoid .unwrap() like hell and propagate errors correctly! 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() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 let parsed: Value = from_reader(data.as_slice()).unwrap(); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let (tag, arr) = parsed.as_tag().unwrap(); assert_eq!(tag, 18); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 6 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let arr = arr.as_array().unwrap(); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let payload = arr[2].as_bytes().unwrap(); payload.clone() // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 let arr = arr.as_array().unwrap(); 8 9 10 } 11 12 // ... 13 loige 58
  • 205. // ... fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { // IRL avoid .unwrap() like hell and propagate errors correctly! 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() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 let parsed: Value = from_reader(data.as_slice()).unwrap(); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let (tag, arr) = parsed.as_tag().unwrap(); assert_eq!(tag, 18); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 6 7 let arr = arr.as_array().unwrap(); 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let arr = arr.as_array().unwrap(); // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 8 let payload = arr[2].as_bytes().unwrap(); 9 payload.clone() 10 } 11 12 // ... 13 let payload = arr[2].as_bytes().unwrap(); payload.clone() // ... 1 2 fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { 3 // IRL avoid .unwrap() like hell and propagate errors correctly! 4 let parsed: Value = from_reader(data.as_slice()).unwrap(); 5 let (tag, arr) = parsed.as_tag().unwrap(); 6 assert_eq!(tag, 18); 7 let arr = arr.as_array().unwrap(); 8 9 10 } 11 12 // ... 13 // ... fn get_cwt_payload(data: Vec<u8>) -> Vec<u8> { // IRL avoid .unwrap() like hell and propagate errors correctly! 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() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 loige 58
  • 206. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 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); } fn parse_cwt_payload(data: Vec<u8>) -> Value { // parse the binary data as CBOR todo!() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 loige 59
  • 207. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 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); } fn parse_cwt_payload(data: Vec<u8>) -> Value { // parse the binary data as CBOR todo!() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let parsed_payload = parse_cwt_payload(cwt_payload); use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 9 } 10 11 fn parse_cwt_payload(data: Vec<u8>) -> Value { 12 // parse the binary data as CBOR 13 todo!() 14 } 15 16 // ... 17 loige 59
  • 208. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 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); } fn parse_cwt_payload(data: Vec<u8>) -> Value { // parse the binary data as CBOR todo!() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let parsed_payload = parse_cwt_payload(cwt_payload); use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 9 } 10 11 fn parse_cwt_payload(data: Vec<u8>) -> Value { 12 // parse the binary data as CBOR 13 todo!() 14 } 15 16 // ... 17 fn parse_cwt_payload(data: Vec<u8>) -> Value { // parse the binary data as CBOR todo!() } use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 let parsed_payload = parse_cwt_payload(cwt_payload); 9 } 10 11 12 13 14 15 16 // ... 17 loige 59
  • 209. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 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!("{:#?}", parsed_payload); } fn parse_cwt_payload(data: Vec<u8>) -> Value { from_reader(data.as_slice()).unwrap() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 loige 60
  • 210. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 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!("{:#?}", parsed_payload); } fn parse_cwt_payload(data: Vec<u8>) -> Value { from_reader(data.as_slice()).unwrap() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from_reader(data.as_slice()).unwrap() use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 let parsed_payload = parse_cwt_payload(cwt_payload); 9 println!("{:#?}", parsed_payload); 10 } 11 12 fn parse_cwt_payload(data: Vec<u8>) -> Value { 13 14 } 15 16 // ... 17 loige 60
  • 211. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 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!("{:#?}", parsed_payload); } fn parse_cwt_payload(data: Vec<u8>) -> Value { from_reader(data.as_slice()).unwrap() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from_reader(data.as_slice()).unwrap() use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 let parsed_payload = parse_cwt_payload(cwt_payload); 9 println!("{:#?}", parsed_payload); 10 } 11 12 fn parse_cwt_payload(data: Vec<u8>) -> Value { 13 14 } 15 16 // ... 17 println!("{:#?}", parsed_payload); use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 let parsed_payload = parse_cwt_payload(cwt_payload); 9 10 } 11 12 fn parse_cwt_payload(data: Vec<u8>) -> Value { 13 from_reader(data.as_slice()).unwrap() 14 } 15 16 // ... 17 loige 60
  • 212. use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 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!("{:#?}", parsed_payload); } fn parse_cwt_payload(data: Vec<u8>) -> Value { from_reader(data.as_slice()).unwrap() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from_reader(data.as_slice()).unwrap() use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 let parsed_payload = parse_cwt_payload(cwt_payload); 9 println!("{:#?}", parsed_payload); 10 } 11 12 fn parse_cwt_payload(data: Vec<u8>) -> Value { 13 14 } 15 16 // ... 17 println!("{:#?}", parsed_payload); use ciborium::{de::from_reader, value::Value}; 1 2 fn main() { 3 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 4 let no_prefix = remove_prefix(cert_data); 5 let decoded = decode_base45(no_prefix); 6 let decompressed = decompress(decoded); 7 let cwt_payload = get_cwt_payload(decompressed); 8 let parsed_payload = parse_cwt_payload(cwt_payload); 9 10 } 11 12 fn parse_cwt_payload(data: Vec<u8>) -> Value { 13 from_reader(data.as_slice()).unwrap() 14 } 15 16 // ... 17 use ciborium::{de::from_reader, value::Value}; fn main() { let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 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!("{:#?}", parsed_payload); } fn parse_cwt_payload(data: Vec<u8>) -> Value { from_reader(data.as_slice()).unwrap() } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 loige 60
  • 215. Ok, let's make it more readable... 😅 loige 62
  • 216. Ok, let's make it more readable... 😅 loige cargo add serde_json 62
  • 217. 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 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()); } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 loige 63
  • 218. 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 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()); } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 use serde_json::to_string_pretty; use ciborium::{de::from_reader, value::Value}; 1 2 3 fn main() { 4 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 5 let no_prefix = remove_prefix(cert_data); 6 let decoded = decode_base45(no_prefix); 7 let decompressed = decompress(decoded); 8 let cwt_payload = get_cwt_payload(decompressed); 9 let parsed_payload = parse_cwt_payload(cwt_payload); 10 println!("{}", to_string_pretty(&parsed_payload).unwrap()); 11 } 12 13 // ... 14 loige 63
  • 219. 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 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()); } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 use serde_json::to_string_pretty; use ciborium::{de::from_reader, value::Value}; 1 2 3 fn main() { 4 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 5 let no_prefix = remove_prefix(cert_data); 6 let decoded = decode_base45(no_prefix); 7 let decompressed = decompress(decoded); 8 let cwt_payload = get_cwt_payload(decompressed); 9 let parsed_payload = parse_cwt_payload(cwt_payload); 10 println!("{}", to_string_pretty(&parsed_payload).unwrap()); 11 } 12 13 // ... 14 println!("{}", to_string_pretty(&parsed_payload).unwrap()); use ciborium::{de::from_reader, value::Value}; 1 use serde_json::to_string_pretty; 2 3 fn main() { 4 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 5 let no_prefix = remove_prefix(cert_data); 6 let decoded = decode_base45(no_prefix); 7 let decompressed = decompress(decoded); 8 let cwt_payload = get_cwt_payload(decompressed); 9 let parsed_payload = parse_cwt_payload(cwt_payload); 10 11 } 12 13 // ... 14 loige 63
  • 220. 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 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()); } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 use serde_json::to_string_pretty; use ciborium::{de::from_reader, value::Value}; 1 2 3 fn main() { 4 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 5 let no_prefix = remove_prefix(cert_data); 6 let decoded = decode_base45(no_prefix); 7 let decompressed = decompress(decoded); 8 let cwt_payload = get_cwt_payload(decompressed); 9 let parsed_payload = parse_cwt_payload(cwt_payload); 10 println!("{}", to_string_pretty(&parsed_payload).unwrap()); 11 } 12 13 // ... 14 println!("{}", to_string_pretty(&parsed_payload).unwrap()); use ciborium::{de::from_reader, value::Value}; 1 use serde_json::to_string_pretty; 2 3 fn main() { 4 let cert_data = "HC1:NCFOXN%TSMAHN-H9QCGDSB5QPN9OO3:D4$X4-365KN-TMLV4 5 let no_prefix = remove_prefix(cert_data); 6 let decoded = decode_base45(no_prefix); 7 let decompressed = decompress(decoded); 8 let cwt_payload = get_cwt_payload(decompressed); 9 let parsed_payload = parse_cwt_payload(cwt_payload); 10 11 } 12 13 // ... 14 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 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()); } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 loige 63
  • 224. A better (& more complete) implementation as a Rust library loige github.com/rust-italia/dgc 66
  • 225. Exercise for the viewer: Try to validate the signature loige 67
  • 226. Exercise for the viewer: Try to validate the signature loige 🔑You can get the Public Key from the certificate here: loige.link/green-examples 67
  • 227. Exercise for the viewer: Try to validate the signature loige 🔑You can get the Public Key from the certificate here: loige.link/green-examples 📑Here you can find more about how the CoseSign1 protocol works: loige.link/cose-sign-verif 67
  • 228. Exercise for the viewer: Try to validate the signature loige 🔑You can get the Public Key from the certificate here: loige.link/green-examples 📑Here you can find more about how the CoseSign1 protocol works: loige.link/cose-sign-verif 📦You could use a crate like for crypto! ring 67
  • 229. Exercise for the viewer: Try to validate the signature loige 🔑You can get the Public Key from the certificate here: loige.link/green-examples 📑Here you can find more about how the CoseSign1 protocol works: loige.link/cose-sign-verif 📦You could use a crate like for crypto! ring (Spoiler: I implemented some of this stuff in my library!) 67
  • 230. Is all this stuff legal? 😰 loige 68
  • 231. Is all this stuff legal? 😰 loige 👀You can certainly look into your certificate (and the test certificates!) 68
  • 232. Is all this stuff legal? 😰 loige 👀You can certainly look into your certificate (and the test certificates!) 🗣Looking into other people's certificate will disclose a lot of privacy-sensitive info (thread carefully) 68
  • 233. Is all this stuff legal? 😰 loige 👀You can certainly look into your certificate (and the test certificates!) 🗣Looking into other people's certificate will disclose a lot of privacy-sensitive info (thread carefully) 📲Building a validator app? Check your country's regulation (especially if you need to store data!) 68
  • 234. Cover Picture by on ❤  Huge thanks to for some precius review sessions and many pull requests! ❤ Thanks to , , , ,  for reviews and suggestions. FPVmat A Unsplash rust-italia @gbinside @88_eugen @AlleviTommaso @npmccallum @pelger loige ☝nodejsdp.link loige.link/green THANK YOU! ❤ 69