Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

When I saw how dense the European Covid Green Pass QR code is, I got immediately curious: "WOW, there must be a lot of interesting data in here". So, I started to dig deeper and I found that there's really a great wealth of interesting encoding and verification technologies being used in it! In this talk, I will share what I learned! We will go on a journey where we will explore Base54 encoding, COSE tokens, CBOR serialization, elliptic curve crypto, and much more! Finally, I will also show you how to write a decoder for Green Pass certificates in the most hyped language ever: Rust!

Luciano Mammino

December 01, 2021
Tweet

More Decks by Luciano Mammino

Other Decks in Technology

Transcript

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

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

    Senior Architect @ fourTheorem (Dublin ) nodejsdp.link 📔 Co-Author of Node.js Design Patterns 👉 3
  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
  4. 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
  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
  6. Agenda + Goals loige 1. Needs and principles 2. 🗝

    Cryptographic model 3. 📦 The data 4. 🧅 Layers of encoding 5. 🛠 Decoding in Rust 6
  7. 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
  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
  9. 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
  10. 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
  11. Electronic Health Certificates (HCERT) Requirements & Guiding Principles loige ✍

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

    Signed data with machine readable content 📃 Use compact encoding 🤲 Based on open standards 10
  13. Asymmetric cryptographic signatures loige 🤫 Private Key 📢 Public Key

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

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

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

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

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

    101010101000101010010... 0101010101010101010101... The owner of the private key signs the document 12
  19. 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
  20. 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
  21. What's inside a certificate? loige DGC container Cryptographic header (Key

    Id, Algorithm) Cryptographic Signature Header (Issuer, Issue date, expiry date) 13
  22. 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)
  23. 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)
  24. { "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
  25. { "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
  26. { "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
  27. { "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
  28. Layered encoding loige QRCODE ASCII mode Prefix + Base45 encoding

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

    Zlib compression CWT signed data (COSE) CBOR document 16 🧅
  30. 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
  31. 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
  32. 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
  33. loige Allows to encode binary data in text format (ASCII)

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

    Like Base64, but it uses 45 characters instead: loige.link/base45-explained Base45 19
  35. Base45 loige 01001001 00100000 01100111 01101111 01110100 00100000 01101101 01111001

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

    00100000 01110011 01101000 01101111 01110100 01110011 00100000 11011000 00111101 Some binary data 20
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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
  47. 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
  48. CBOR loige It also supports: Byte String (a sequence of

    raw bytes) Tags (annotations that allow to create new types) 32
  49. CBOR loige An example: A3 63666F6F 63626172 686D616E7976616C73 83 01

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

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

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

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

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

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

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

    02 03 666E6573746564 A0 { "foo": "bar", "manyvals": [ } ], "nested": {} 1, 2, 3 33
  57. COSE / CWT loige CBOR Object Signing and Encryption /

    CBOR Web Token ok... again 😅 34
  58. COSE loige CBOR Object Signing and Encryption COSE (inspired by

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

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

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

    ) defines CBOR-based protocols for: JOSE Encrypted data Cryptographic signed data MACed data 35
  62. 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
  63. CWT loige Like but for CBOR JWT Defines a protocol

    for transferring claims between parties CBOR Web Token 36
  64. 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
  65. 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
  66. CWT loige A CWT is made of 4 parts: Protected

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

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

    header CBOR Web Token Non protected header Payload Signature 37
  69. 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
  70. Protected header Binary String loige Array (length 4) CWT tag

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

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

    39 Unprotected header Map (length 0) Payload Binary String Signature Binary String
  73. 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
  74. 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
  75. How to decode - quick recap loige 1. Remove "HC1:"

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

    prefix 2. Base45 decode 3. Zlib decompress 4. Parse CWT 41
  77. 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
  78. 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
  79. 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
  80. 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
  81. 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
  82. // 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
  83. // 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
  84. // 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
  85. // 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
  86. 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
  87. 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
  88. 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
  89. 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
  90. 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
  91. 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
  92. 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
  93. 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
  94. 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
  95. 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
  96. 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
  97. 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
  98. 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
  99. 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
  100. 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
  101. 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
  102. 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
  103. 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
  104. 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
  105. 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
  106. 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
  107. 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
  108. 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
  109. Are we on the right track? loige We are starting

    to see some readable info! 🤩 53
  110. 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
  111. 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
  112. 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
  113. 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
  114. loige cargo add ciborium # Cargo.toml # ... [dependencies] base45

    = "3.0.0" ciborium = "0.2.0" inflate = "0.4.5" 55
  115. 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
  116. 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
  117. 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
  118. // ... 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
  119. // ... 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
  120. // ... 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
  121. // ... 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
  122. // ... 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
  123. // ... 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
  124. 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
  125. 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
  126. 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
  127. 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
  128. 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
  129. 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
  130. 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
  131. 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
  132. 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
  133. 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
  134. 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
  135. 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
  136. 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
  137. 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
  138. 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
  139. Is all this stuff legal? 😰 loige 👀 You can

    certainly look into your certificate (and the test certificates!) 68
  140. 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
  141. 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
  142. 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