Slide 1

Slide 1 text

A look inside the European Covid Green Certificate Luciano Mammino ( ) @loige 2021-12-01 loige.link/green 1

Slide 2

Slide 2 text

Get these slides! loige loige.link/green 2

Slide 3

Slide 3 text

Let me introduce myself first... 3

Slide 4

Slide 4 text

Let me introduce myself first... 👋 I'm Luciano ( 🍕🍝) 3

Slide 5

Slide 5 text

Let me introduce myself first... 👋 I'm Luciano ( 🍕🍝) Senior Architect @ fourTheorem (Dublin ) 3

Slide 6

Slide 6 text

Let me introduce myself first... 👋 I'm Luciano ( 🍕🍝) Senior Architect @ fourTheorem (Dublin ) nodejsdp.link 📔 Co-Author of Node.js Design Patterns 👉 3

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Disclaimers loige 5

Slide 10

Slide 10 text

Disclaimers loige 🤓 I am not involved with the DGC working group 5

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Agenda + Goals loige 6

Slide 13

Slide 13 text

Agenda + Goals loige 1. Needs and principles 2. 🗝 Cryptographic model 3. 📦 The data 4. 🧅 Layers of encoding 5. 🛠 Decoding in Rust 6

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

The need for a digital certificate in the COVID age loige 7

Slide 16

Slide 16 text

The need for a digital certificate in the COVID age loige 8

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

The EU Covid Green Pass a.k.a. Electronic Health Certificates (HCERT) loige.link/hcert-spec loige 9

Slide 21

Slide 21 text

Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige 10

Slide 22

Slide 22 text

Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige ✍ Signed data with machine readable content 10

Slide 23

Slide 23 text

Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige ✍ Signed data with machine readable content 📃 Use compact encoding 10

Slide 24

Slide 24 text

Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige ✍ Signed data with machine readable content 📃 Use compact encoding 🤲 Based on open standards 10

Slide 25

Slide 25 text

Asymmetric cryptographic signatures loige 11

Slide 26

Slide 26 text

Asymmetric cryptographic signatures loige 🤫 Private Key 101010101000101010010... 11

Slide 27

Slide 27 text

Asymmetric cryptographic signatures loige 🤫 Private Key 📢 Public Key 101010101000101010010... 0101010101010101010101... 11

Slide 28

Slide 28 text

Asymmetric cryptographic signatures loige 🤫 Private Key 📢 Public Key 🔗 101010101000101010010... 0101010101010101010101... 11

Slide 29

Slide 29 text

Asymmetric cryptographic signatures loige 🤫 Private Key 📢 Public Key 101010101000101010010... 0101010101010101010101... 12

Slide 30

Slide 30 text

Asymmetric cryptographic signatures loige 🤫 Private Key 📢 Public Key 101010101000101010010... 0101010101010101010101... 12

Slide 31

Slide 31 text

Asymmetric cryptographic signatures loige 🤫 Private Key 📢 Public Key 101010101000101010010... 0101010101010101010101... The owner of the private key signs the document 12

Slide 32

Slide 32 text

Asymmetric cryptographic signatures loige 🤫 Private Key 📢 Public Key 101010101000101010010... 0101010101010101010101... The owner of the private key signs the document 12

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

What's inside a certificate? loige 13

Slide 36

Slide 36 text

What's inside a certificate? loige 13

Slide 37

Slide 37 text

What's inside a certificate? loige Cryptographic header (Key Id, Algorithm) 13

Slide 38

Slide 38 text

What's inside a certificate? loige DGC container Cryptographic header (Key Id, Algorithm) 13

Slide 39

Slide 39 text

What's inside a certificate? loige DGC container Cryptographic header (Key Id, Algorithm) Cryptographic Signature 13

Slide 40

Slide 40 text

What's inside a certificate? loige DGC container Cryptographic header (Key Id, Algorithm) Cryptographic Signature Header (Issuer, Issue date, expiry date) 13

Slide 41

Slide 41 text

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)

Slide 42

Slide 42 text

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)

Slide 43

Slide 43 text

An example loige loige.link/green-examples 14

Slide 44

Slide 44 text

An example loige loige.link/green-examples 15

Slide 45

Slide 45 text

{ "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

Slide 46

Slide 46 text

{ "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

Slide 47

Slide 47 text

{ "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

Slide 48

Slide 48 text

{ "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

Slide 49

Slide 49 text

Layered encoding loige 16 🧅

Slide 50

Slide 50 text

Layered encoding loige QRCODE ASCII mode 16 🧅

Slide 51

Slide 51 text

Layered encoding loige QRCODE ASCII mode Prefix + Base45 encoding 16 🧅

Slide 52

Slide 52 text

Layered encoding loige QRCODE ASCII mode Prefix + Base45 encoding Zlib compression 16 🧅

Slide 53

Slide 53 text

Layered encoding loige QRCODE ASCII mode Prefix + Base45 encoding Zlib compression CWT signed data (COSE) 16 🧅

Slide 54

Slide 54 text

Layered encoding loige QRCODE ASCII mode Prefix + Base45 encoding Zlib compression CWT signed data (COSE) CBOR document 16 🧅

Slide 55

Slide 55 text

loige QRCode content 17

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

Base45 loige 18

Slide 60

Slide 60 text

loige Base45 19

Slide 61

Slide 61 text

loige Allows to encode binary data in text format (ASCII) Base45 19

Slide 62

Slide 62 text

loige Allows to encode binary data in text format (ASCII) Like Base64, but it uses 45 characters instead: Base45 19

Slide 63

Slide 63 text

loige Allows to encode binary data in text format (ASCII) Like Base64, but it uses 45 characters instead: loige.link/base45-explained Base45 19

Slide 64

Slide 64 text

Base45 loige 20

Slide 65

Slide 65 text

Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001 00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 Some binary data 20

Slide 66

Slide 66 text

Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001 00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 Some binary data 20

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

loige Base45 22

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

Zlib compression loige 23

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

Zlib compression loige 25

Slide 79

Slide 79 text

Zlib compression loige Compressed binary data 25

Slide 80

Slide 80 text

Zlib compression loige Zlib inflate Compressed binary data 25

Slide 81

Slide 81 text

Zlib compression loige Zlib inflate Compressed binary data Decompressed binary data 25

Slide 82

Slide 82 text

Zlib compression loige 26

Slide 83

Slide 83 text

Zlib compression loige 26

Slide 84

Slide 84 text

Zlib compression loige 👀 We start to see some "readable" information! 26

Slide 85

Slide 85 text

COSE / CWT loige CBOR Object Signing and Encryption / CBOR Web Token 27

Slide 86

Slide 86 text

CBOR !? 🤔 loige But wait, what the heck is ✋ 28

Slide 87

Slide 87 text

CBOR loige TLDR; Like JSON but in binary! loige.link/cbor-rfc 29

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

CBOR loige It also supports: Byte String (a sequence of raw bytes) Tags (annotations that allow to create new types) 32

Slide 91

Slide 91 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 33

Slide 92

Slide 92 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { } 33

Slide 93

Slide 93 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": } 33

Slide 94

Slide 94 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", } 33

Slide 95

Slide 95 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": } 33

Slide 96

Slide 96 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], 33

Slide 97

Slide 97 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], 1, 33

Slide 98

Slide 98 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], 1, 2, 33

Slide 99

Slide 99 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], 1, 2, 3 33

Slide 100

Slide 100 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], "nested": 1, 2, 3 33

Slide 101

Slide 101 text

CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01 02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], "nested": {} 1, 2, 3 33

Slide 102

Slide 102 text

COSE / CWT loige CBOR Object Signing and Encryption / CBOR Web Token ok... again 😅 34

Slide 103

Slide 103 text

COSE loige CBOR Object Signing and Encryption 35

Slide 104

Slide 104 text

COSE loige CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE 35

Slide 105

Slide 105 text

COSE loige CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE Encrypted data 35

Slide 106

Slide 106 text

COSE loige CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE Encrypted data Cryptographic signed data 35

Slide 107

Slide 107 text

COSE loige CBOR Object Signing and Encryption COSE (inspired by ) defines CBOR-based protocols for: JOSE Encrypted data Cryptographic signed data MACed data 35

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

CWT loige CBOR Web Token 36

Slide 110

Slide 110 text

CWT loige Like but for CBOR JWT CBOR Web Token 36

Slide 111

Slide 111 text

CWT loige Like but for CBOR JWT Defines a protocol for transferring claims between parties CBOR Web Token 36

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

CWT loige CBOR Web Token 37

Slide 115

Slide 115 text

CWT loige A CWT is made of 4 parts: CBOR Web Token 37

Slide 116

Slide 116 text

CWT loige A CWT is made of 4 parts: Protected header CBOR Web Token 37

Slide 117

Slide 117 text

CWT loige A CWT is made of 4 parts: Protected header CBOR Web Token Non protected header 37

Slide 118

Slide 118 text

CWT loige A CWT is made of 4 parts: Protected header CBOR Web Token Non protected header Payload 37

Slide 119

Slide 119 text

CWT loige A CWT is made of 4 parts: Protected header CBOR Web Token Non protected header Payload Signature 37

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

loige 39

Slide 122

Slide 122 text

loige 39

Slide 123

Slide 123 text

loige CWT tag 39

Slide 124

Slide 124 text

loige CWT tag 39

Slide 125

Slide 125 text

loige Array (length 4) CWT tag 39

Slide 126

Slide 126 text

loige Array (length 4) CWT tag 39

Slide 127

Slide 127 text

Protected header Binary String loige Array (length 4) CWT tag 39

Slide 128

Slide 128 text

Protected header Binary String loige Array (length 4) CWT tag 39

Slide 129

Slide 129 text

Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0)

Slide 130

Slide 130 text

Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0)

Slide 131

Slide 131 text

Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0) Payload Binary String

Slide 132

Slide 132 text

Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0) Payload Binary String

Slide 133

Slide 133 text

Protected header Binary String loige Array (length 4) CWT tag 39 Unprotected header Map (length 0) Payload Binary String Signature Binary String

Slide 134

Slide 134 text

loige CWT payload 40

Slide 135

Slide 135 text

loige CWT payload 40

Slide 136

Slide 136 text

loige CWT payload Binary String follows (CBOR Encoded) 40

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

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

Slide 139

Slide 139 text

How to decode - quick recap loige 41

Slide 140

Slide 140 text

How to decode - quick recap loige 1. Remove "HC1:" prefix 41

Slide 141

Slide 141 text

How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 41

Slide 142

Slide 142 text

How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 41

Slide 143

Slide 143 text

How to decode - quick recap loige 1. Remove "HC1:" prefix 2. Base45 decode 3. Zlib decompress 4. Parse CWT 41

Slide 144

Slide 144 text

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

Slide 145

Slide 145 text

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

Slide 146

Slide 146 text

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

Slide 147

Slide 147 text

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

Slide 148

Slide 148 text

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

Slide 149

Slide 149 text

loige cargo new dgc-decode Project bootstrap 42

Slide 150

Slide 150 text

// 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

Slide 151

Slide 151 text

// 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

Slide 152

Slide 152 text

// 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

Slide 153

Slide 153 text

// 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

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

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

Slide 156

Slide 156 text

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

Slide 157

Slide 157 text

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

Slide 158

Slide 158 text

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

Slide 159

Slide 159 text

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

Slide 160

Slide 160 text

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

Slide 161

Slide 161 text

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 { 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

Slide 162

Slide 162 text

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 { 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 { 11 todo!() 12 // parse the string as base45 encoded and return the 13 // resulting raw bytes 14 } 15 16 // ... 17 loige 46

Slide 163

Slide 163 text

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 { 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 { 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 { 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

Slide 164

Slide 164 text

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 { 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 { 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 { 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 { 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

Slide 165

Slide 165 text

loige cargo add base45 47

Slide 166

Slide 166 text

loige cargo add base45 # Cargo.toml # ... [dependencies] base45 = "3.0.0" 47

Slide 167

Slide 167 text

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 { 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

Slide 168

Slide 168 text

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 { 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 { 11 12 } 13 14 // ... 15 loige 48

Slide 169

Slide 169 text

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 { 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 { 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 { 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

Slide 170

Slide 170 text

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) -> Vec { todo!() // decompress using zlib inflate } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 loige 49

Slide 171

Slide 171 text

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) -> Vec { 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) -> Vec { 11 todo!() 12 // decompress using zlib inflate 13 } 14 15 // ... 16 loige 49

Slide 172

Slide 172 text

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) -> Vec { 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) -> Vec { 11 todo!() 12 // decompress using zlib inflate 13 } 14 15 // ... 16 fn decompress(data: Vec) -> Vec { 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

Slide 173

Slide 173 text

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) -> Vec { 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) -> Vec { 11 todo!() 12 // decompress using zlib inflate 13 } 14 15 // ... 16 fn decompress(data: Vec) -> Vec { 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) -> Vec { todo!() // decompress using zlib inflate } // ... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 loige 49

Slide 174

Slide 174 text

loige cargo add inflate 50

Slide 175

Slide 175 text

loige cargo add inflate # Cargo.toml # ... [dependencies] base45 = "3.0.0" inflate = "0.4.5" 50

Slide 176

Slide 176 text

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) -> Vec { 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

Slide 177

Slide 177 text

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) -> Vec { 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) -> Vec { 11 12 13 } 14 15 // ... 16 loige 51

Slide 178

Slide 178 text

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) -> Vec { 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) -> Vec { 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) -> Vec { 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

Slide 179

Slide 179 text

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

Slide 180

Slide 180 text

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

Slide 181

Slide 181 text

Are we on the right track? loige 53

Slide 182

Slide 182 text

Are we on the right track? loige We are starting to see some readable info! 🤩 53

Slide 183

Slide 183 text

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) -> Vec { 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

Slide 184

Slide 184 text

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) -> Vec { 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) -> Vec { 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

Slide 185

Slide 185 text

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) -> Vec { 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) -> Vec { 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) -> Vec { 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

Slide 186

Slide 186 text

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) -> Vec { 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) -> Vec { 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) -> Vec { 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) -> Vec { 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

Slide 187

Slide 187 text

loige cargo add ciborium 55

Slide 188

Slide 188 text

loige cargo add ciborium # Cargo.toml # ... [dependencies] base45 = "3.0.0" ciborium = "0.2.0" inflate = "0.4.5" 55

Slide 189

Slide 189 text

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) -> Vec { 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

Slide 190

Slide 190 text

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) -> Vec { 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) -> Vec { 13 let parsed: Value = from_reader(data.as_slice()).unwrap(); 14 println!("{:?}", parsed); 15 todo!() 16 } 17 18 // ... 19 loige 56

Slide 191

Slide 191 text

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) -> Vec { 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) -> Vec { 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) -> Vec { 13 14 15 todo!() 16 } 17 18 // ... 19 loige 56

Slide 192

Slide 192 text

57 loige

Slide 193

Slide 193 text

57 loige

Slide 194

Slide 194 text

CWT Tag (18) 57 loige

Slide 195

Slide 195 text

The content is an array 57 loige

Slide 196

Slide 196 text

57 Protected header loige

Slide 197

Slide 197 text

57 Non protected header loige

Slide 198

Slide 198 text

57 Payload ✅ loige

Slide 199

Slide 199 text

57 Signature loige

Slide 200

Slide 200 text

// ... fn get_cwt_payload(data: Vec) -> Vec { // 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

Slide 201

Slide 201 text

// ... fn get_cwt_payload(data: Vec) -> Vec { // 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) -> Vec { 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

Slide 202

Slide 202 text

// ... fn get_cwt_payload(data: Vec) -> Vec { // 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) -> Vec { 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) -> Vec { 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

Slide 203

Slide 203 text

// ... fn get_cwt_payload(data: Vec) -> Vec { // 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) -> Vec { 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) -> Vec { 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) -> Vec { 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

Slide 204

Slide 204 text

// ... fn get_cwt_payload(data: Vec) -> Vec { // 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) -> Vec { 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) -> Vec { 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) -> Vec { 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) -> Vec { 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

Slide 205

Slide 205 text

// ... fn get_cwt_payload(data: Vec) -> Vec { // 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) -> Vec { 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) -> Vec { 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) -> Vec { 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) -> Vec { 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) -> Vec { // 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

Slide 206

Slide 206 text

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) -> 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

Slide 207

Slide 207 text

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) -> 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) -> Value { 12 // parse the binary data as CBOR 13 todo!() 14 } 15 16 // ... 17 loige 59

Slide 208

Slide 208 text

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) -> 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) -> Value { 12 // parse the binary data as CBOR 13 todo!() 14 } 15 16 // ... 17 fn parse_cwt_payload(data: Vec) -> 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

Slide 209

Slide 209 text

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) -> 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

Slide 210

Slide 210 text

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) -> 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) -> Value { 13 14 } 15 16 // ... 17 loige 60

Slide 211

Slide 211 text

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) -> 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) -> 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) -> Value { 13 from_reader(data.as_slice()).unwrap() 14 } 15 16 // ... 17 loige 60

Slide 212

Slide 212 text

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) -> 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) -> 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) -> 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) -> 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

Slide 213

Slide 213 text

loige 61

Slide 214

Slide 214 text

loige 61

Slide 215

Slide 215 text

Ok, let's make it more readable... 😅 loige 62

Slide 216

Slide 216 text

Ok, let's make it more readable... 😅 loige cargo add serde_json 62

Slide 217

Slide 217 text

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

Slide 218

Slide 218 text

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

Slide 219

Slide 219 text

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

Slide 220

Slide 220 text

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

Slide 221

Slide 221 text

loige 64

Slide 222

Slide 222 text

loige 64

Slide 223

Slide 223 text

All the code: loige.link/green-code loige 65

Slide 224

Slide 224 text

A better (& more complete) implementation as a Rust library loige github.com/rust-italia/dgc 66

Slide 225

Slide 225 text

Exercise for the viewer: Try to validate the signature loige 67

Slide 226

Slide 226 text

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

Slide 227

Slide 227 text

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

Slide 228

Slide 228 text

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

Slide 229

Slide 229 text

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

Slide 230

Slide 230 text

Is all this stuff legal? 😰 loige 68

Slide 231

Slide 231 text

Is all this stuff legal? 😰 loige 👀 You can certainly look into your certificate (and the test certificates!) 68

Slide 232

Slide 232 text

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

Slide 233

Slide 233 text

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

Slide 234

Slide 234 text

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