{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pass sanitaire\n",
    "\n",
    "Le QR-code contient un fichier binaire encodé en [base 45](https://datatracker.ietf.org/doc/draft-faltstrom-base45/), précdé d'un en-tête `HC1:`.\n",
    "\n",
    "Ce fichier est compressé au format [zlib](https://docs.python.org/fr/3/library/zlib.html).\n",
    "\n",
    "Sa décompression est une structure [CBOR](https://cbor.io/).\n",
    "\n",
    "Le pass est rendu infalsifiable grâce à une signature numérique utilisant les courbes elliptiques.\n",
    "\n",
    "\n",
    "Les modules [base45](https://pypi.org/project/base45/), [cbor2](https://pypi.org/project/cbor2/) \n",
    "et [ecdsa](https://pypi.org/project/ecdsa/) sont à installer préalablement."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import base45, cbor2, zlib, json\n",
    "from time import ctime\n",
    "from base64 import *\n",
    "import codecs\n",
    "import ecdsa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# un exemple de données lues en flashant un QR-code\n",
    "x = '''HC1:6BFOXN%TSMAHN-H3YS1IK47ES6IXJR4E47X5*T917VF+UOGIS1RYZV:X9:IMJZTCV4*XUA2PSGH.+H$NI4L6HUC%UG/YL WO*Z7ON13:LHNG7H8H%BFP8FG4T 9OKGUXI$NIUZUK*RIMI4UUIMI.J9WVHWVH+ZEOV1AT1HRI2UHD4TR/S09T./08H0AT1EYHEQMIE9WT0K3M9UVZSVV*001HW%8UE9.955B9-NT0 2$$0X4PCY0+-CVYCRMTB*05*9O%0HJP7NVDEBO584DKH78$ZJ*DJWP42W5P0QMO6C8PL353X7H1RU0P48PCA7T5MCH5:ZJ::AKU2UM97H98$QP3R8BH9LV3*O-+DV8QJHHY4I4GWU-LU7T9.V+ T%UNUWUG+M.1KG%VWE94%ALU47$71MFZJU*HFW.6$X50*MSYOJT1MR96/1Z%FV3O-0RW/Q.GMCQS%NE'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'HC1:6BFOXN%TSMAHN-H3YS1IK47ES6IXJR4E47X5*T917VF+UOGIS1RYZV:X9:IMJZTCV4*XUA2PSGH.+H$NI4L6HUC%UG/YL WO*Z7ON13:LHNG7H8H%BFP8FG4T 9OKGUXI$NIUZUK*RIMI4UUIMI.J9WVHWVH+ZEOV1AT1HRI2UHD4TR/S09T./08H0AT1EYHEQMIE9WT0K3M9UVZSVV*001HW%8UE9.955B9-NT0 2$$0X4PCY0+-CVYCRMTB*05*9O%0HJP7NVDEBO584DKH78$ZJ*DJWP42W5P0QMO6C8PL353X7H1RU0P48PCA7T5MCH5:ZJ::AKU2UM97H98$QP3R8BH9LV3*O-+DV8QJHHY4I4GWU-LU7T9.V+ T%UNUWUG+M.1KG%VWE94%ALU47$71MFZJU*HFW.6$X50*MSYOJT1MR96/1Z%FV3O-0RW/Q.GMCQS%NE'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "45"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(set(x)) # il y a bien 45 caractères différents ..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'x\\x9c\\xbb\\xd4\\xe2\\xbb\\x88Q\\x8d\\xc5\\xe3y\\xa1_o\\xfd\\x8f\\x8c\\xd9\\x0b\"\\x1e-aLq\\xf6s\\xf4e\\x91J\\xd5\\xdc\\xfb\\x80M*\\xb1\\\\\\xeb\\x9f%#\\xf3B\\xc6%\\x89e\\x8d\\xab\\x92\\x923+dC\\x83\\xfc\\xacB\\xc3\\x9c=\\xad\\x0c\\x0c\\xad\\xdc\\x82\\xacBL]\\xc2C\\xbc\"\\x83M\\xa2\\x82,\\x94M\\x92\\x92\\xf3\\x93\\xdc\\x82\\x92R\\xf2\\x98\\x92RJ\\xb2\\x8c\\x0c\\x8c\\x0cu\\r\\rt\\r\\x0c\\x932\\x8b\\xc1\\xe6&\\xe5&\\xe6\\xfa\\x07\\xb9\\x03\\x05\\r\\x0c\\x8c\\x81\\xb2\\xa6I\\xb9\\x059\\xae\\xa1\\xfa\\x86\\xfaF\\x06\\xfa\\x86\\xa6F\\x16I\\xc5)LI%\\xe9\\x99\\x16&\\x06\\xa6\\xc6\\x96\\x06\\x06fIe\\x05\\xe9^\\x06\\xe6N\\x11\\x06\\xc6\\xc9)\\xf9IY\\x86@A\\xa0\\x81@\\x94\\x9c\\x97\\x98\\xbb$)-/\\xcd\\xc33\\xc4\\xc75()=/\\xd5\\xd1\\xc5\\xdf\\xc7-9-\\xaf\\x04*\\x96\\x9c\\x9eW\\x02\\x15,K-J5\\xd43\\xd63\\x88p\\xf8\\xf1\\xc4\\xb6n\\x06\\xcf1\\x89\\x89\\x8f8\\xff\\xf4\\xadp\\xe6\\xbe\\xfc\\xa2\\xeb\\xe1\\xbb[\\xf3\\x0c\\xb5\\x1e\\x9e\\x8b\\xfb\\xf5I\\xc7U\\xcc$\\xff=\\xe7z\\x86\\xf0\\xc8y\\xcb6\\xf8-\\x7f\\xb4\\xe1\\xc3\\xee\\r\\x15L\\x06\\x0f~}x\\xbe~\\xd5\\xbc\\xd5Y\\xb1\\x00\\xe2\\x1ar\\xef'"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Il faut retirer l'en-tête HC1:\n",
    "base45.b45decode(x[4:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = _"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'\\xd2\\x84M\\xa2\\x01&\\x04H\\xe7qN\\x8d\\x7f\\xf8h\\x9b\\xa0X\\xe2\\xa4\\x01dCNAM\\x04\\x1ae)\\xbd\\xe0\\x06\\x1aaw*\\xfe9\\x01\\x03\\xa1\\x01\\xa4av\\x81\\xaabcix\\x1dURN:UVCI:01:FR:T5DWTJYS4ZR8#4bcobFRbdn\\x02bdtj2021-10-01bisdCNAMbmamORG-100030215bmplEU/1/20/1528bsd\\x02btgi840539006bvpgJ07BX03cdobj1900-01-01cnam\\xa4bfnfHITLERbgneADOLFcfntfHITLERcgnteADOLFcvere1.3.0X@\\xf8\\xe4=~\\x98\\x0c\\xc6\\x18\\x91\\xe2\\t\\xfc\\x8e\\xa8C\\x0b\\xd3\\xe8\\x8a\\xe1\\xee\\xda\\x9e1*\\xe1\\xce^\\xfa\\xf2,E\\x164o\\xef\\t\\xaf\\x00WY\\x9e\\xa6\\xb0N\\xa7\\xe2\\xb0\\xf0\\xbb\\xb0x\\x020\\xe0\\xfa\\xf0\\xe7\\xaf\\xaa\\x9e\\xabj]'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zlib.decompress(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# C'est une structure CBOR qu'il faut décoder\n",
    "cb = _"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "CBORTag(18, [b'\\xa2\\x01&\\x04H\\xe7qN\\x8d\\x7f\\xf8h\\x9b', {}, b'\\xa4\\x01dCNAM\\x04\\x1ae)\\xbd\\xe0\\x06\\x1aaw*\\xfe9\\x01\\x03\\xa1\\x01\\xa4av\\x81\\xaabcix\\x1dURN:UVCI:01:FR:T5DWTJYS4ZR8#4bcobFRbdn\\x02bdtj2021-10-01bisdCNAMbmamORG-100030215bmplEU/1/20/1528bsd\\x02btgi840539006bvpgJ07BX03cdobj1900-01-01cnam\\xa4bfnfHITLERbgneADOLFcfntfHITLERcgnteADOLFcvere1.3.0', b'\\xf8\\xe4=~\\x98\\x0c\\xc6\\x18\\x91\\xe2\\t\\xfc\\x8e\\xa8C\\x0b\\xd3\\xe8\\x8a\\xe1\\xee\\xda\\x9e1*\\xe1\\xce^\\xfa\\xf2,E\\x164o\\xef\\t\\xaf\\x00WY\\x9e\\xa6\\xb0N\\xa7\\xe2\\xb0\\xf0\\xbb\\xb0x\\x020\\xe0\\xfa\\xf0\\xe7\\xaf\\xaa\\x9e\\xabj]'])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cbor2.decoder.loads(cb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le tag 18 indique un [COSE Single Signer Data Object](https://www.iana.org/go/draft-ietf-cose-rfc8152bis-struct-15)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "loads = _"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[b'\\xa2\\x01&\\x04H\\xe7qN\\x8d\\x7f\\xf8h\\x9b',\n",
       " {},\n",
       " b'\\xa4\\x01dCNAM\\x04\\x1ae)\\xbd\\xe0\\x06\\x1aaw*\\xfe9\\x01\\x03\\xa1\\x01\\xa4av\\x81\\xaabcix\\x1dURN:UVCI:01:FR:T5DWTJYS4ZR8#4bcobFRbdn\\x02bdtj2021-10-01bisdCNAMbmamORG-100030215bmplEU/1/20/1528bsd\\x02btgi840539006bvpgJ07BX03cdobj1900-01-01cnam\\xa4bfnfHITLERbgneADOLFcfntfHITLERcgnteADOLFcvere1.3.0',\n",
       " b'\\xf8\\xe4=~\\x98\\x0c\\xc6\\x18\\x91\\xe2\\t\\xfc\\x8e\\xa8C\\x0b\\xd3\\xe8\\x8a\\xe1\\xee\\xda\\x9e1*\\xe1\\xce^\\xfa\\xf2,E\\x164o\\xef\\t\\xaf\\x00WY\\x9e\\xa6\\xb0N\\xa7\\xe2\\xb0\\xf0\\xbb\\xb0x\\x020\\xe0\\xfa\\xf0\\xe7\\xaf\\xaa\\x9e\\xabj]']"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "loads.value"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ce premier décodage produit une liste de 4 champs.\n",
    "\n",
    "Le premier est un dictionnaire dont la clé 1 (valeur -7) indique l'algorithme cryptographique utilisé, et la clé 4\n",
    "est une valeur binaire dont l'encodage en base 64 donne l'identifiant (*kid*) de la clé publique.\n",
    "\n",
    "Le second champ est un dictionnaire inutilisé (vide).\n",
    "\n",
    "Le troisième contient les informations du certificat, et le quatrième est une signature numérique."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{1: -7, 4: b'\\xe7qN\\x8d\\x7f\\xf8h\\x9b'}\n",
      "**** {}\n",
      "{-260: {1: {'dob': '1900-01-01',\n",
      "            'nam': {'fn': 'HITLER',\n",
      "                    'fnt': 'HITLER',\n",
      "                    'gn': 'ADOLF',\n",
      "                    'gnt': 'ADOLF'},\n",
      "            'v': [{'ci': 'URN:UVCI:01:FR:T5DWTJYS4ZR8#4',\n",
      "                   'co': 'FR',\n",
      "                   'dn': 2,\n",
      "                   'dt': '2021-10-01',\n",
      "                   'is': 'CNAM',\n",
      "                   'ma': 'ORG-100030215',\n",
      "                   'mp': 'EU/1/20/1528',\n",
      "                   'sd': 2,\n",
      "                   'tg': '840539006',\n",
      "                   'vp': 'J07BX03'}],\n",
      "            'ver': '1.3.0'}},\n",
      " 1: 'CNAM',\n",
      " 4: 1697234400,\n",
      " 6: 1635199742}\n",
      "CBORSimpleValue(value=228)\n"
     ]
    }
   ],
   "source": [
    "# Ici, les données sont un peu étranges, le pass n'est certainement pas valide !\n",
    "import pprint\n",
    "for a in loads.value:\n",
    "    try:\n",
    "        pprint.pprint (cbor2.decoder.loads(a))\n",
    "    except: print ('****', str(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Sat Oct 14 00:00:00 2023'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ctime(1697234400) # 4: est censé être la date d'émission (2023=erreur ?)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Tue Oct 26 00:09:02 2021'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ctime(1635199742) # 6: est censé être la date de fin de validité (erreur ?)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "D'après le [site](https://univalence.io/blog/articles/decoder-le-passe-sanitaire/) :\n",
    "\n",
    "Le champ annoté -260 contient les faits à l'origine du certificat.\n",
    "\n",
    "- version du schéma de certificat utilisé (clé ver). \n",
    "- une structure  nom (clé nam), également encodé comme  en bas des cartes d'identité ou des passeports. \n",
    "- date de naissance (clé dob).\n",
    "- liste des vaccins (clé v). \n",
    "- Pour chaque acte de \"vaccination\", un identifiant unique appelé UVCI (clé ci), \n",
    "- pays émetteur (clé co). \n",
    "- nombre de doses reçues (clé sd)\n",
    "- nombre de doses nécessaires (clé dn), \n",
    "- date de la dernière dose (clé dt), \n",
    "- code du fabricant du vaccin (clé ma) \n",
    "- code produit administré (clé mp) \n",
    "- agent ciblé (clé tg — c'est la Covid-19), le type d'administration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'53FOjX/4aJs='"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# le kid (key identifier)\n",
    "b64encode(b'\\xe7qN\\x8d\\x7f\\xf8h\\x9b')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "kid = _.decode('ascii')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Les clés publiques du système sont rassemblées dans un [fichier](Digital_Green_Certificate_Signing_Keys.json) `json` publiquement accessible."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'53FOjX/4aJs='"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kid"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\t\"53FOjX/4aJs=\": {\r\n",
      "\t\t\"serialNumber\": \"6e3a243ea72c2bd04f6bd51d59ec497b212a8a5a\",\r\n",
      "\t\t\"subject\": \"C=FR, O=CNAM, OU=180035024, CN=DSC_FR_023\",\r\n",
      "\t\t\"issuer\": \"C=FR, O=Gouv, CN=CSCA-FRANCE\",\r\n",
      "\t\t\"notBefore\": \"2021-10-14T22:00:00.000Z\",\r\n",
      "\t\t\"notAfter\": \"2023-10-14T22:00:00.000Z\",\r\n",
      "\t\t\"signatureAlgorithm\": \"RSASSA-PKCS1-v1_5\",\r\n",
      "\t\t\"fingerprint\": \"be552cc91a5fe934268b9db169db6349311ad693\",\r\n",
      "\t\t\"publicKeyAlgorithm\": {\r\n",
      "\t\t\t\"hash\": {\r\n",
      "\t\t\t\t\"name\": \"SHA-256\"\r\n",
      "\t\t\t},\r\n",
      "\t\t\t\"name\": \"ECDSA\",\r\n",
      "\t\t\t\"namedCurve\": \"P-256\"\r\n",
      "\t\t},\r\n",
      "\t\t\"publicKeyPem\": \"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgu/WJBn1Q+RCOfQx3NLT5oIGUCHsqSRXuu7EZsqfqZN5PvHk6/E++88wvj2fMrfmAptk5tVld2xBH4P4tRs8JQ==\"\r\n",
      "\t},\r\n"
     ]
    }
   ],
   "source": [
    "!grep -B 0 -C 16  53FOjX/4aJs= Digital_Green_Certificate_Signing_Keys.json"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'53FOjX/4aJs='"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kid = b64encode(cbor2.decoder.loads(loads.value[0])[4]).decode('ascii')\n",
    "kid"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgu/WJBn1Q+RCOfQx3NLT5oIGUCHsqSRXuu7EZsqfqZN5PvHk6/E++88wvj2fMrfmAptk5tVld2xBH4P4tRs8JQ=='"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "with open('Digital_Green_Certificate_Signing_Keys.json') as f:\n",
    "    keys = json.load(f)\n",
    "    keypem = keys[kid]['publicKeyPem']\n",
    "\n",
    "keypem"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le module `ecdsa` (Elliptic Curve Digital Signature Algorithm) permet de vérifier la signature (à condition de savoir\n",
    "comment le message est composé). Il faut préciser la fonction de hachage (sha256 ici)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "VerifyingKey.from_string(b'\\x03\\x82\\xef\\xd6$\\x19\\xf5C\\xe4B9\\xf41\\xdc\\xd2\\xd3\\xe6\\x82\\x06P!\\xec\\xa9$W\\xba\\xee\\xc4f\\xca\\x9f\\xa9\\x93', NIST256p, sha256)"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ecdsa.VerifyingKey.from_pem(keypem, hashfunc=ecdsa.util.sha256)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "vk = _"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'\\xf8\\xe4=~\\x98\\x0c\\xc6\\x18\\x91\\xe2\\t\\xfc\\x8e\\xa8C\\x0b\\xd3\\xe8\\x8a\\xe1\\xee\\xda\\x9e1*\\xe1\\xce^\\xfa\\xf2,E\\x164o\\xef\\t\\xaf\\x00WY\\x9e\\xa6\\xb0N\\xa7\\xe2\\xb0\\xf0\\xbb\\xb0x\\x020\\xe0\\xfa\\xf0\\xe7\\xaf\\xaa\\x9e\\xabj]'"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# On récupère la signature\n",
    "sg = loads.value[3]\n",
    "sg"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "64"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(sg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le message à signer est un tableau CBOR composé de la chaîne \"Signature1\", du champ 0, une chaîne vide, et le champ 2 (données) de la structure originale. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "info  = loads.value[2]\n",
    "xx  = [ \"Signature1\", loads.value[0], b'', info]\n",
    "msg = cbor2.encoder.dumps(xx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Signature1',\n",
       " b'\\xa2\\x01&\\x04H\\xe7qN\\x8d\\x7f\\xf8h\\x9b',\n",
       " b'',\n",
       " b'\\xa4\\x01dCNAM\\x04\\x1ae)\\xbd\\xe0\\x06\\x1aaw*\\xfe9\\x01\\x03\\xa1\\x01\\xa4av\\x81\\xaabcix\\x1dURN:UVCI:01:FR:T5DWTJYS4ZR8#4bcobFRbdn\\x02bdtj2021-10-01bisdCNAMbmamORG-100030215bmplEU/1/20/1528bsd\\x02btgi840539006bvpgJ07BX03cdobj1900-01-01cnam\\xa4bfnfHITLERbgneADOLFcfntfHITLERcgnteADOLFcvere1.3.0']"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xx"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'\\x84jSignature1M\\xa2\\x01&\\x04H\\xe7qN\\x8d\\x7f\\xf8h\\x9b@X\\xe2\\xa4\\x01dCNAM\\x04\\x1ae)\\xbd\\xe0\\x06\\x1aaw*\\xfe9\\x01\\x03\\xa1\\x01\\xa4av\\x81\\xaabcix\\x1dURN:UVCI:01:FR:T5DWTJYS4ZR8#4bcobFRbdn\\x02bdtj2021-10-01bisdCNAMbmamORG-100030215bmplEU/1/20/1528bsd\\x02btgi840539006bvpgJ07BX03cdobj1900-01-01cnam\\xa4bfnfHITLERbgneADOLFcfntfHITLERcgnteADOLFcvere1.3.0'"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cbor2.encoder.dumps(xx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "msg=_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vk.verify(sg,msg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "La signature est valide ! L'infalsifiable a été falsifié !\n",
    "\n",
    "Que s'est il  passé ?\n",
    "\n",
    "L'enquête est en cours, voir [cet article](https://www.liberation.fr/checknews/comment-des-pass-sanitaires-valides-de-bob-leponge-ou-adolf-hitler-ont-ils-pu-se-retrouver-en-ligne-20211028_GKJOCBG345EDZLVQRWT2WY5FVA/)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
