nsi:tds:cryptographie:blockchain
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| nsi:tds:cryptographie:blockchain [2023/04/11 17:45] – goupillwiki | nsi:tds:cryptographie:blockchain [2023/05/08 01:14] (Version actuelle) – goupillwiki | ||
|---|---|---|---|
| Ligne 73: | Ligne 73: | ||
| </ | </ | ||
| - | === Bloc d' | + | === Blocs d' |
| Les blocs ordinaires recevront l' | Les blocs ordinaires recevront l' | ||
| Ligne 80: | Ligne 80: | ||
| <code python> | <code python> | ||
| - | (" | + | (" |
| </ | </ | ||
| - | === Information supplémentaire === | + | * Paul est la source (il donne de crédits) |
| + | * Judith est la cible (elle reçoit les crédits) | ||
| + | * 5 est la quantité de crédits échangés | ||
| + | * S est la signature permettant d' | ||
| + | |||
| + | Voir plus bas pour le fonctionnement de la signature. | ||
| Le bloc s' | Le bloc s' | ||
| Ligne 89: | Ligne 94: | ||
| * données (initialisation pour le bloc 0 et transaction pour les autres) | * données (initialisation pour le bloc 0 et transaction pour les autres) | ||
| - | Pour le hachage, on pourra utiliser | + | On utilise |
| <code python> | <code python> | ||
| Ligne 104: | Ligne 109: | ||
| <WRAP tip>On peut indiquer l' | <WRAP tip>On peut indiquer l' | ||
| + | |||
| + | === Signature === | ||
| + | |||
| + | Dans la transaction '' | ||
| + | |||
| + | Voyons comment la signature sera crée : | ||
| + | * Paul veut donner 5 unité à Judith. On crée le texte '' | ||
| + | * on encode le texte et on hache. On utilise pour cela '' | ||
| + | * on calcule la signature '' | ||
| + | * '' | ||
| + | * la transaction est alors complétée : '' | ||
| + | |||
| + | Dans l' | ||
| + | |||
| + | <code python> | ||
| + | ' | ||
| + | </ | ||
| + | |||
| + | Au moment de la vérification, | ||
| + | |||
| + | * comme dans ce qui précède, on produit le texte '' | ||
| + | * on hache ce texte : '' | ||
| + | * on cherche la version '' | ||
| + | * on déchiffre '' | ||
| + | * on compare si '' | ||
| === Sauvegarde === | === Sauvegarde === | ||
| - | Il peut être intéressant de sauvegarder un bloc sous forme d'un fichier. | + | Chaque |
| - | On pourra par exemple sauvegarder un bloc sous cette forme : | + | |
| + | Le fichier aura pour nom l' | ||
| + | |||
| + | Dans le cas du bloc initial, le bloc contiendra simplement les données. Par exemple | ||
| <code lang-none> | <code lang-none> | ||
| - | empreinte du bloc précédent en format hexdigest | + | Paul; |
| - | chaque ligne de donnée avec séparateur | + | Judith;92; |
| - | empreinte du bloc en format hexdigest | + | Michel; |
| + | Laure; | ||
| </ | </ | ||
| - | Il faudrait donc aussi prévoir de créer | + | Dans le cas d'un bloc d'échange, le bloc contiendra la transaction. Par exemple '' |
| - | ==== Chaîne ==== | + | Le fichier contient donc : |
| + | nom de la source;nom de la cible;str de value;hex de S | ||
| - | Créons une classe '' | + | === chargement === |
| - | Un objet '' | + | Si je sais que le dernier bloc à l'empreinte E, alors je peux chercher un fichier |
| + | * nom de la source | ||
| + | * nom de la cible | ||
| + | * value que l'on peut convertir en int | ||
| + | * signature qui est sous forme hex et que l'on peut passer en '' | ||
| - | La classe '' | + | ==== Chaîne ==== |
| - | * ajouter un bloc : on donne une transaction, | + | |
| - | * lire l' | + | |
| - | ==== Signature ==== | + | Créons une classe '' |
| - | Dans la transaction | + | * L' |
| + | * chaque fois que la blockchain charge un bloc, elle lit l'empreinte de ce bloc et cherche s'il existe un fichier nommer d' | ||
| - | Quand l' | + | Le bloc initial indique le compte initial des utilisateurs. Les transactions indiquent des échanges d'un utilisateur à l'autre. |
| - | * calculer '' | + | |
| - | * chiffrer '' | + | |
| - | * fournir '' | + | |
| - | <WRAP box> | + | Ainsi, si Paul commence à 45, Judith |
| - | * on fabrique le texte '' | + | |
| - | * on fait l' | + | On peut garder |
| - | * on calcule | + | |
| - | * on obtient | + | |
| - | * reste à chiffrer avec Kpr de Paul : '' | + | |
| - | On obtiendra ici pour '' | ||
| <code python> | <code python> | ||
| - | b"\x12\xd1\xcc\x8b' | + | comptes = { |
| + | | ||
| + | " | ||
| + | " | ||
| + | "Laure":39 | ||
| + | } | ||
| </ | </ | ||
| - | et on place ce '' | + | La blockchain, au gré des transactions, met à jour les valeurs des différents comptes. |
| - | </ | + | |
| - | Pour vérifier la signature, on doit : | + | Il pourra être utile aussi de créer, à la lecture de '' |
| - | * calculer '' | + | |
| - | * déchiffrer '' | + | |
| - | * vérifier que '' | + | |
| - | La signature permet de s' | + | <code python> |
| + | keys = { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | </ | ||
| - | <WRAP tip>On aimerait ajouter une méthode dans '' | + | === ajout de transaction |
| - | ==== Vérification d'un bloc ==== | + | La classe |
| - | Lors de l' | + | Une transaction |
| - | * vérifier que la signature est valide, | + | |
| - | * vérifier que la demande est valide compte-tenu des comptes en l' | + | |
| - | ==== Sauvegarde ==== | + | la blockchain doit : |
| + | * vérifier que les identifiants existent, | ||
| + | * vérifier la signature, | ||
| + | * vérifier que la source dispose d' | ||
| - | Il serait intéressant de prévoir | + | On convient que la fonction renvoie |
| - | Il faudrait alors prévoir de recréer la chaîne | + | * mise à jour des comptes, |
| + | * création du bloc correspondant, | ||
| + | * ajout du bloc à la suite des autres, | ||
| + | * sauvegarde | ||
| - | Vous pouvez aussi sauvegarder la chaîne | + | et dans ce cas la fonction renvoie |
| ===== Proposition d' | ===== Proposition d' | ||
| Ligne 180: | Ligne 223: | ||
| <code python> | <code python> | ||
| + | # blockchain.py | ||
| import hashlib | import hashlib | ||
| + | import os | ||
| import rsa | import rsa | ||
| - | class Bloc: | + | class Block: |
| def __init__(self, | def __init__(self, | ||
| """ | """ | ||
| Ligne 197: | Ligne 242: | ||
| """ | """ | ||
| # mettre empreinte_precedent, | # mettre empreinte_precedent, | ||
| - | # suivi du version texte de data | + | # suivi de la version texte de data (__str__ ci dessous) |
| # encoder en utf8 pour obtenir un bytes b | # encoder en utf8 pour obtenir un bytes b | ||
| # faire le hash avec hashlib.sha256(b) | # faire le hash avec hashlib.sha256(b) | ||
| Ligne 211: | Ligne 256: | ||
| """ | """ | ||
| sauvegarde le bloc dans un fichier dont le nom est l' | sauvegarde le bloc dans un fichier dont le nom est l' | ||
| - | du bloc précédent suivit de l' | + | du bloc précédent suivit de l' |
| """ | """ | ||
| # le fichier doit contenir le contenu de __str__ | # le fichier doit contenir le contenu de __str__ | ||
| - | # si le fichier existe, il ne faut rien faire | + | # si le fichier existe |
| + | |||
| + | def next_filename(self) -> str: | ||
| + | """ | ||
| + | renvoie le nom de fichier du bloc suivant | ||
| + | """ | ||
| + | return self.FOLDER + self.empreinte() + self.EXT | ||
| Ligne 222: | Ligne 273: | ||
| lance la procédure de chargement pour construire la blockchain | lance la procédure de chargement pour construire la blockchain | ||
| """ | """ | ||
| + | self.blocs = [] | ||
| + | self.keys = {} | ||
| + | self.credits = {} | ||
| self.load() | self.load() | ||
| Ligne 234: | Ligne 288: | ||
| # les infos des comptes sous la forme : identifiant: | # les infos des comptes sous la forme : identifiant: | ||
| # | # | ||
| - | # crée le bloc0 avec les infos du fichier mettre bloc0 dans self.blocs | + | # créer |
| + | # créer un self.keys = { identifiant: | ||
| + | # créer un self.credits = { identifiant: | ||
| # à partir de là, tant que l' | # à partir de là, tant que l' | ||
| - | # charger le fichier | + | # charger le fichier, lire la transaction, |
| - | + | ||
| - | + | | |
| - | | + | |
| - | | + | |
| - | où identifiant est l'identifiant du compte | + | |
| - | credit est la quantité de crédits sur le compte | + | |
| - | (n, e) est la clé publique associée au compte | + | |
| - | Sinon, data est None, alors : | + | |
| - | les données sont lues dans les fichiers | + | |
| - | """ | + | |
| | | ||
| - | # si data != None | ||
| - | # il faut créer le premier bloc : bloc0 | ||
| - | # puis créer la chaine, | ||
| - | # par exemple c'est c'est un tableau contenant bloc0 | ||
| - | # [bloc0] | ||
| - | # peut aussi créer un dictionnaire comptes récupérant les infos du bloc 0 | ||
| - | # comptes = { identifiant: | ||
| - | # au gré des transactions, | ||
| - | # remarque : rien ne vous empêche de créer une classe pour structurer les comtpes... | ||
| - | # si data = | ||
| - | | ||
| def add_transaction(id_source: | def add_transaction(id_source: | ||
| """ | """ | ||
| Ligne 270: | Ligne 308: | ||
| # vérifie la signature | # vérifie la signature | ||
| # vérifie si le compte source a assez de crédits | # vérifie si le compte source a assez de crédits | ||
| + | # modifie l' | ||
| # crée un bloc pour la transaction | # crée un bloc pour la transaction | ||
| + | # en indiquant l' | ||
| # ajoute le bloc dans la liste des blocs | # ajoute le bloc dans la liste des blocs | ||
| # sauvegarder le bloc | # sauvegarder le bloc | ||
| - | # modifie l' | ||
| def empreinte_transaction(self, | def empreinte_transaction(self, | ||
| Ligne 280: | Ligne 319: | ||
| id_cible: identifiant cible | id_cible: identifiant cible | ||
| value: quantité | value: quantité | ||
| - | renvoie l' | + | renvoie l' |
| """ | """ | ||
| # fabrique le texte formé de la façon id_source; | # fabrique le texte formé de la façon id_source; | ||
| - | # encode, hash, | + | # encode, hash |
| - | # renvoie digest() | + | # renvoie digest |
| - | + | ||
| - | def save_bloc(self): | + | def credit(self, identifiant: |
| """ | """ | ||
| - | | + | |
| """ | """ | ||
| + | </ | ||
| + | |||
| + | Il faudra donc créer manuellement un bloc initial '' | ||
| + | <code lang-none> | ||
| + | Paul; | ||
| + | Judith; | ||
| + | Michel; | ||
| + | Laure; | ||
| + | </ | ||
| + | |||
| + | On a besoin de simuler un client agissant sur la blockchain (un des utilisateurs). Si par exemple Paul veut faire une transaction, | ||
| + | <code python> | ||
| + | # client.py | ||
| + | |||
| + | import hashlib | ||
| + | import rsa | ||
| + | |||
| + | class Client: | ||
| + | def __init__(self, | ||
| + | """ | ||
| + | identifiant: | ||
| + | Kpr: clé privée (n,d) | ||
| + | """ | ||
| + | self.identifiant = identifiant | ||
| + | self.Kpr = Kpr | ||
| | | ||
| - | def read_bloc_file(filename:str): | + | def transaction(self, id_cible:str, value:int): |
| """ | """ | ||
| - | | + | |
| """ | """ | ||
| - | # il faut ouvrir | + | # la transaction signée est formée ainsi : |
| + | # (id_source, id_cible, value, signature) | ||
| + | # pour le calcul de la signature, on reprend le principe | ||
| + | # rencontré dans BlockChain.empreinte_transaction : | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # le résultat est la signature | ||
| + | </ | ||
| + | On pourra par montrer le fonctionnement de la façon suivante : | ||
| + | |||
| + | < | ||
| + | # demo.py | ||
| + | |||
| + | from blockchain import BlockChain | ||
| + | from client import Client | ||
| + | |||
| + | b = BlockChain() # charge le fichier 0.bloc | ||
| + | paul = Client(" | ||
| + | judith = Client(" | ||
| + | |||
| + | print(f" | ||
| + | print(f" | ||
| + | t = paul.transaction(" | ||
| + | success = b.add_transaction(*t) # * pour ventiler les morceaux du tuple t dans les arguments | ||
| + | |||
| + | if success: | ||
| + | print(" | ||
| + | # la transaction a été enregistrée et sera donc pris en compte | ||
| + | # à la prochaine exécution du script | ||
| + | else: | ||
| + | print(" | ||
| </ | </ | ||
| + | | ||
| + | | ||
nsi/tds/cryptographie/blockchain.1681227932.txt.gz · Dernière modification : de goupillwiki
