Blog traitant d'informatique, de programmation, de python, de golang, de linux...
Bref, en chiffrant vos fichiers avec le script pyFC, ces divers fournisseurs pourront toujours les consulter (en utilisant un éditeur hexadécimal, par exemple), mais de là à en tirer quelque chose, c'est une autre histoire...
...enfin revenons à nos moutons : le masque jetable, vous connaissez ? Voici la définition de wikipedia :
“Le masque jetable, également appelé chiffre de Vernam, est un algorithme de cryptographie inventé par Gilbert Vernam en 1917 et perfectionné par Joseph Mauborgne, qui rajouta la notion de clé aléatoire....
...
....tant pour le codage que pour le décodage, ce chiffrement est théoriquement impossible à casser,....”
Le principe de ce chiffrement est de crypter tous les caractères du message ou du fichier à protéger, et ce de manière unique et aléatoire. La clé de cryptage devra donc être de longueur au moins équivalente au message d'origine, ne devra être utilisée qu'une seule fois, et être générée aléatoirement.
L'implémentation de ce script respecte en outre le principe de Kerckhoffs (reformulé par Claude Shannon), qui stipule que « l'adversaire connaît le système ». Ce système de chiffrement et son implémentation n'auront donc rien de secret, la sécurité reposant essentiellement sur le secret des clés.
Le système de chiffrement dont il est question ici est un système à clé symétrique : une même clé sert à la fois au chiffrement et au déchiffrement.
Le script pyFC :
Pour rappel, le but de pyFC est de chiffrer vos fichiers pour votre utilisation personnelle essentiellement. Il n'est pas question ici pour le moment de transmettre des clés à un éventuel correspondant (voir la section "Évolutions futures" pour ce point) afin qu'il déchiffre les fichiers transmis. Cela reste possible, mais il vous faudra alors transmettre vos clés de chiffrement par un autre moyen (clé usb essentiellement...).
1ère étape : Génération des clés :
Pour générer les clés de chiffrement, placez-vous dans le répertoire du script puis dans une console entrez:
you@yourComputer:~/pyFC$ python3 pyFC.py -init
Le script vous demande alors confirmation comme quoi vous souhaitez bien générer un nouveau jeu de clés, entrez 'OK'.
Je parle ici de clés au pluriel, ou de jeu de clés. En fait, le script va générer 5 fichiers remplis d'octets aléatoires dont les tailles feront respectivement 100MBytes, 200MBytes, 300MBytes, 400MBytes et 500MBytes. Ces fichiers seront créés chacun dans une arborescence de répertoires contenant 28 niveaux, et seront stockés au 'dernier étage' (ou bien dernier sous-sol, selon la manière dont on visualise cela) de cette arborescence. Les noms de chacun de ses répertoires seront générés aléatoirement (sur 3 lettres et/ou chiffres) et précédés d'un point ('.') permettant ainsi de cacher chaque niveau de ces arborescences. Les noms des fichiers clés seront respectivement '.key1', '.key2', '.key3', '.key4', '.key5'.
Une fois ces fichiers clés générés, le script vous demandera d'entrer l'emplacement (répertoire) où vous souhaitez stocker ces arborescences de clés. Il est préférable de les placer ailleurs que dans le répertoire du script, pour des raisons évidentes de sécurité. Si vous n'entrez rien, les clés resteront dans ce répertoire courant.
J'ai choisi volontairement des clés relativement volumineuses afin qu'elle ne puissent pas être facilement transmises par le réseau. La sécurité de ce système est assuré tant que le secret des clés l'est, ce qui est vrai pour n'importe quel système de chiffrement.
La liste des emplacement de ces 5 arborescences de clés sera sauvée dans votre dossier utilisateur dans le fichier de configuration :
/home/user/.pyFC/.pyFC.conf
Ce fichier de configuration ainsi que toutes les arborescences où sont stockées les clés verront tous leurs droits d'accès mis à 0 (chmod 0o000). Il ne seront ainsi plus lisibles directement (même si l'utilisateur courant peut changer ces droits). Les droits seront gérés par le script selon les besoins, mais seront toujours remis à 0o000 après toute opération de chiffrement ou déchiffrement. Seule l'option "-showconf" passée en paramètre (voir plus bas son utilisation) permet de dévérouiller la sécurité, jusqu'au prochain lancement du script.
2ème étape : Chiffrement d'un fichier ou d'un répertoire :
Dans la console, entrez :
you@yourComputer:~/pyFC$ python3 /cheminvers/pyFC.py -e /chemindufichier/oudurépertoire/àchiffrer
Par exemple :
you@yourComputer:~/pyFC$ python3 /home/adam/pyFC/pyFC.py -e /DataDisk2/mesPhotos/390485.mov
Ici, le paramètre -e indique que l'on souhaite chiffrer le fichier 390485.mov. pyFC va alors créer une archive zip temporaire nommée crypted.zip. Cela permettra à la fois de ne travailler que sur cette seule archive (donc process identique que l'on ait à chiffrer un simple fichier ou un répertoire complet), et en même temps de ne pas avoir à se préoccuper du stockage du nom de fichier/répertoire d'origine puisque celui-ci sera contenu dans cette archive. Ensuite, pyFC va générer 5 nombres aléatoires (1 par fichier clé, chaque nombre étant >=0 et < (à la taille de clé - la taille de l'archive précédemment créée). Ce nombre indique l'offset dans chaque fichier clé à partir duquel on va lire une série de N bytes, N étant la taille de l'archive zip. On a maintenant 5 bytearray(s) avec lesquels on va chiffrer (par opération XOR) notre archive. Pour chaque byte 'en clair' de l'archive, on obtient le byte chiffré par l'opération suivante :
byteChiffré = byteClair^byteSérie1^byteSérie2^byteSérie3^byteSérie4^byteSérie5
Il ne nous reste plus qu'à stocker notre nouveau tableau de bytes chiffrés dans un fichier, sans oublier d'y placer en entête les 5 offsets utilisés qui seront nécessaires au déchiffrage. On peut considérer ces offsets comme une partie de la clé, aussi pour ne pas dévoiler une partie du secret trop facilement, on va coder ces informations. Dans un premier temps, on va encoder chaque offset sur 4 octets (format integer 32 bits), 'mélanger' l'ordre de leurs octets [Byte3 Byte2 Byte1 Byte0] devient [Byte0 Byte2 Byte3 Byte1], puis les combiner par opération XOR chacun avec 2 séries de 4 octets pris dans les fichiers clés, l'offset choisi pour chaque série dépendant de la taille de l'archive à chiffrer passée par une opération modulo. Vous pouvez voir les détails de ce process directement dans le code source plus bas.
De manière totalement subjective, j'ai choisi de nommer les fichiers chiffrés à partir de la valeur 'Unix timestamp' relevée juste après la création de l'archive. L'extension par défaut est ".000".
Cas de fichier d'archive >100MBytes :
Tel que défini plus haut, on peut voir qu'il n'est pas prévu de chiffrer des fichiers de taille > 100MBytes (puisque 100MBytes est la taille de la plus petite clé). Cela est résolu en découpant l'archive en 'tranches' plus petites. Après quelques séries de tests, je me suis aperçu que chiffrer des fichiers de quelques dizaines de mégabytes était de toute façon une opération assez longue. Aussi, j'ai choisi de découper les fichiers selon la formule suivante afin de gagner en temps, ou tout au moins avoir une meilleure visibilité de ce qui se passe lors du chiffrement/déchiffrement :
Taille_Tranche_Max = 3MBytes + 1MByte*[(Taille de l'archive en clair(en MBytes)) / 15]
Pour un fichier de 5MBytes, vous obtiendrez Taille_Tranche_Max = 3 MBytes --> soit 2 tranches de 2.5 MBytes
Pour un fichier de 33MBytes, vous obtiendrez Taille_Tranche_Max = 5 MBytes --> soit 7 tranches de 4.7 MBytes
Pour un fichier de 189MBytes, vous obtiendrez Taille_Tranche_Max = 15 MBytes --> soit 13 tranches de 14.5 MBytes
La limite haute de Taille_Tranche_Max est de 50MBytes. Le nombre de fichiers résultant(s) est calculé automatiquement, et pour savoir qu'un ensemble de fichiers fait référence à une même archive, ceux-ci porteront tous le même nom (le 'Unix timestamp'). Seule l'extension changera : le 1er fichier portant l'extension ".000", le suivant ".001", le suivant ".002", etc... selon le nombre de fichiers nécessaire(s)...
3ème étape : Déchiffrement d'un fichier "crypté" :
Dans la console, entrez :
you@yourComputer:~/pyFC$ python3 /cheminvers/pyFC.py -d /chemindufichier/oudurépertoire/àdéchiffrer
Par exemple :
you@yourComputer:~/pyFC$ python3 /home/adam/pyFC/pyFC.py -d /DataDisk2/mesPhotos/1561243871.000
Ici, le paramètre -d indique que l'on souhaite déchiffrer le fichier "1561243871.000". Dans le principe, si d'autres fichiers dans le même répertoire portant le même nom avec d'autres extensions (".001", ".002", etc) existent, ils seront pris en compte comme faisant partie d'un même ensemble de fichiers à déchiffrer. Le fichier ou répertoire d'origine sera alors extrait / recréé à partir de l'ensemble des fichiers chiffrés. Attention, le nom du fichier passé en paramètre pour déchiffrement doit forcément avoir une extension en ".000" ! N'essayez pas de déchiffrer un fichier avec extension ".001", ".002" ou autres extension, cela ne fonctionnera pas !
Autres options du script :
Pour obtenir de l'aide :
you@yourComputer:~/pyFC$ python3 pyFC.py -help
Pour accéder au fichier de configuration ainsi qu'aux clés (ré-autorise les accès en lecture/écriture aux fichiers et répertoires de clés) :
you@yourComputer:~/pyFC$ python3 pyFC.py -showconf
Pour interdire les accès au fichier de configuration ainsi qu'aux clés (interdit les accès en lecture/écriture) :
you@yourComputer:~/pyFC$ python3 pyFC.py -hideconf
L'option -showconf peut-être utilisée si vous souhaitez (dé)placer vos clés dans des répertoires de base différents. Pourquoi pas dans ce cas en placer une ou deux sur clé(s) USB, qui servirai(en)t de dongle de sécurité, par exemple? Dans ce cas, il vous faudra modifier à la mano les chemins vers les clés dans le fichier /home/user/.pyFC/.pyFC.conf
Évolutions futures :
Une première évolution utile serait de pouvoir produire plusieurs jeux de clés et de les nommer afin de pouvoir les utiliser en tant que clés partagées avec divers correspondants. Une autre possible serait de pouvoir choisir la taille ainsi que le nombre de clés à utiliser, même si cela me parait moins utile pour le moment... Disons que le script est déjà assez long (je l'imaginais plus court au début de ce projet), et me parait tout à fait utilisable et cohérent pour une première version...
Je reconnais aussi qu'utiliser un script en ligne de commande, c'est parfois un peu lourd, ça peut freiner un peu l'envie d'essayer... Pour ce point, j'écrirai un prochain article où j'explique comment je l'utilise directement à partir des options disponibles en clic droit dans mon navigateur de fichiers (caja).
Vous trouverez le code de ce script juste ci-après, et vous pouvez le télécharger ici. C'est un fichier zip qui contient un répertoire /pyFC qui contient lui-même le fichier pyFC.py ainsi qu'un fichier secrets.py. Ce dernier fichier (secrets.py) fait partie de la librairie standard de python3.6, mais n'est pas fourni dans les versions précédentes. Le fait de l'avoir directement dans /pyFC permet de faire fonctionner pyFC.py sous python3.5 sans problème, mais je n'ai pas pu tester l'ensemble sous une version encore antérieure... Le script a été testé sous LinuxMint 19.1 et Debian 9.9.
Si vous avez d'autres idées, des questions ou des suggestions, n'hésitez pas à m'en faire part dans vos commentaires. En attendant, prenez bien soin de votre vie privée :-)
PS : Au passage, un grand merci à mon beta-testeur préféré qui m'a permis de constater cette différence entre les versions de python3.5 et 3.6 :-)
Script pyFC.py :
1 #!/usr/bin/env python3 2 # -*- coding: utf-8 -*- 3 # V0.1 du 24/06/2019 4 5 6 7 #### 8 # pyFC est le diminutif de pyFileCrypter (qui était le nom originel de ce projet). Trouvant 'pyFileCrypter' un 9 # peu long, j'ai préféré le raccourcir un peu pour gagner en concision... 10 # 11 # NB : Ce script est prévu pour fonctionner sous Linux essentiellement (mais si vous êtes motivé(s), il devrait 12 # être adaptable assez facilement pour d'autres OS...) 13 # 14 # Ce script à pour but de chiffrer/déchiffrer des fichiers ou répertoires en utilisant l'algorithme 15 # du masque jetable, ou chiffre de Vernam. 16 # 17 # INITIALISATION: 18 # Au 1er lancement du script, il faudra lui passer l'argument '-init' (puis valider cette opération par 'OK'), 19 # afin que le jeu de clés de chiffrement soit créé. 20 # Ce jeu consiste en 5 fichiers respectivement de 100, 200, 300, 400 et 500 Mega-Octets, contenant 21 # chacun un ensemble d'octets générés aléatoirement. Les grandes tailles de ces fichiers limitent les risques 22 # de copie, mais surtout d'upload par un "processus pirate" (un upload d'~ 1.5 Giga Octets prendrait beaucoup 23 # de temps !). Chaque fichier clé sera généré dans une nouvelle arborescence de répertoires de 28 'étages' 24 # Une fois ces fichiers clés générés, le script va vous demander d'entrer le répertoire dans lequel vous 25 # souhaitez stoker ces clés. 26 # La console vous indique la marche à suivre. 27 # Après validation (entrée de 'OK' dans la console), le fichier pyFC.conf sera créé dans votre 28 # /home, placé dans un nouveau répertoire caché /.pyFC, puis renommé .pyFC.conf de manière 29 # à devenir un fichier caché lui aussi. 30 # Les droits du répertoire /.pyFC et du fichier .pyFC.conf vont être mis à 0o000 afin d' 31 # améliorer un peu la sécurité (ils deviennent donc illisible tant que les droits de lecture n'auront pas 32 # été réactivés.) 33 # Ces droits de lecture seront réactivés temporairement au prochain lancement du script pyFC.py (par 34 # le script lui-même afin que celui-ci puisse accéder aux clés), puis re-désactivés. 35 # Ce système de protection est aussi appliqué à toute l'arborescence des clés. 36 # 37 # Pour le cas où vous souhaitez pouvoir chiffrer/déchiffrer vos fichiers sur une autre machine avec le même 38 # jeu de clés, il suffira de recopier l'arborescence des clés ainsi que le fichier de configuration sur 39 # ladite machine aux endroits choisis. 40 # Il ne faudra en aucun cas relancer le script avec l'argument '-init', sinon celui-ci écraserait la 41 # configuration du le jeu de clés actuel avec une nouvelle configuration (les clés elles-même ne seront pas 42 # effacées)! Dans une version future, si le besoin s'en fait sentir, j'implémenterai probablement la 43 # possibilité d'avoir plusieurs jeux de clés (ce qui permettrait par exemple d'avoir des jeux de clés 44 # partagés avec différents correspondants...) 45 # 46 # FONCTIONNEMENT & UTILISATION : 47 # Pour chaque fichier à chiffrer, le script va générer aléatoirement 5 offsets différents (1 pour chaque fichier 48 # clé), puis dans chaque fichier clé aller chercher à partir de cet offset un nombre d'octets équivalent à la 49 # taille du fichier à chiffrer. Ensuite, le chiffrement va s'effectuer par un XOR octet par octet comme suit : 50 # temp1 = fichier_à_chiffrer ^ fichier_clé1[offset1, size] 51 # temp2 = temp1 ^ fichier_clé2[offset2, size] 52 # temp3 = temp2 ^ fichier_clé3[offset3, size] 53 # temp4 = temp3 ^ fichier_clé4[offset4, size] 54 # temp5 = temp4 ^ fichier_clé5[offset5, size] 55 # 56 # 57 # Il est aussi nécessaire de stocker les offsets utilisés au sein de chaque fichier chiffré. Ces offsets 58 # sont codés sur 4 octets (nombre hexa 32bits). 59 # A partir de ces données, le script va créer le header du fichier une fois chiffré : 60 # 61 # XXXX -> 4 octets representant l'offset1 : offset1 ^ fichier_clé1 [10000 + 29*(TailleFichier % 9999), 4] 62 # ^ fichier_clé2 [20000 + 113*(TailleFichier % 8888), 4] 63 # -> Poids des octets dans le codage : 0231 64 # XXXX -> 4 octets representant l'offset2 : offset2 ^ fichier_clé2 [30000 + 229*(TailleFichier % 7777), 4] 65 # ^ fichier_clé3 [40000 + 349*(TailleFichier % 6666), 4] 66 # -> Poids des octets dans le codage : 0231 67 # XXXX -> 4 octets representant l'offset3 : offset3 ^ fichier_clé3 [50000 + 463*(TailleFichier % 5555), 4] 68 # ^ fichier_clé4 [60000 + 601*(TailleFichier % 4444), 4] 69 # -> Poids des octets dans le codage : 0231 70 # XXXX -> 4 octets representant l'offset4 : offset4 ^ fichier_clé4 [70000 + 733*(TailleFichier % 3333), 4] 71 # ^ fichier_clé5 [80000 + 863*(TailleFichier % 2222), 4] 72 # -> Poids des octets dans le codage : 0231 73 # XXXX -> 4 octets representant l'offset5 : offset5 ^ fichier_clé5 [90000 + 1013*(TailleFichier % 1111), 4] 74 # ^ fichier_clé1 [100000 + 1151*(TailleFichier % 5432), 4] 75 # -> Poids des octets dans le codage : 0231 76 # 77 # Une fois ce header généré, il sera mis en entête de temp5 (voir plus haut), puis le fichier sera sauvegardé 78 # sous le nom int([time]).EXT ([time] étant le nombre de secondes écoulées depuis le 01/01/1970 79 # EXT aura pour valeur l'index '000', '001', '002' selon le rang du fichier compressé correspondant à 80 # un même fichier non compressé d'origine (cas des fichiers > 100MBytes) 81 # Dans le cas d'une compression en plusieurs 'volumes' (.000, .001, etc...), le time servant à définir 82 # le nom de fichier devra être le même. 83 # 84 # 85 # CAS DU CHIFFREMENT D'UN REPERTOIRE : 86 # Plutôt qu'un simple fichier, pyFC peut chiffrer un répertoire complet en y incluant tous ses 87 # fichiers et sous-répertoires. Pour cela, le répertoire à chiffrer sera dans un premier temps 88 # compressé en fichier zip, puis ensuite traité comme un simple fichier normal. 89 # NB : Il en est de même maintenant pour le chiffrement d'un fichier 'simple'. Celui-ci sera 90 # préalablement archivé dans un zip, avant que ce zip soit chiffré. Cela présente l'avantage de 91 # ne pas avoir à stocker le nom d'origine du fichier (puisqu'il figurera dans l'archive zip). 92 # 93 # 94 # ARGUMENTS : 95 # Pour chiffrer un fichier / répertoire : --> python3 pyFC.py -e [chemin complet vers le fichier 96 # ou répertoire à chiffrer] 97 # Pour déchiffrer un fichier : --> python3 pyFC.py -d [chemin complet vers le fichier 98 # chiffré à déchiffrer] 99 # 100 # 101 # 102 #### 103 104 105 106 107 import os 108 import sys 109 import shutil 110 import secrets 111 import time 112 import random 113 import string 114 import zipfile 115 116 117 118 119 120 def setConfFileAccess(accessibility): 121 ''' Permet de rendre /home/user/.pyFC/.pyFC.conf visible et accessible ou non selon les besoins''' 122 if accessibility: 123 os.chmod(pfcDir, 0o774) # On met les droits de lecture/écriture sur le répertoire 124 os.chmod(pfcConfFile, 0o774) # On met les droits de lecture/écriture sur le fichier conf 125 #todo : gérer le attrib sous win 126 else: 127 os.chmod(pfcDir, 0o774) # On met les droits de lecture/écriture sur le répertoire 128 try: 129 os.chmod(pfcConfFile, 0o000)# On supprime les droits de lecture/écriture sur le répertoire 130 os.chmod(pfcDir, 0o000)# On supprime les droits de lecture/écriture sur le répertoire 131 #todo : gérer le attrib sous win 132 except PermissionError: 133 pass 134 135 136 137 def setKeyfilesAccess(accessibility): 138 ''' Permet de rendre les 5 fichiers clé keyFilePath visibles et accessibles ou non selon les besoins.''' 139 nindex = 0 140 for fullPath in keyFilepathList: 141 if accessibility: # On rend les clés accessibles 142 fullPath = fullPath[0:len(fullPath)-145] 143 for n in range(29): 144 dirStr = keyFilepathList[nindex][0:len(fullPath)+(n+1)*5] 145 os.chmod(dirStr, 0o774) 146 #todo : gérer le attrib sous win 147 else: # On rend les clés inaccessibles 148 for n in range(29): 149 dirStr = keyFilepathList[nindex][0:len(fullPath)-n*5] 150 try: 151 os.chmod(dirStr, 0o000) 152 #todo : gérer le attrib sous win 153 except PermissionError: 154 pass 155 nindex += 1 156 157 158 159 def removeRNFromListe(listName): 160 ''' Enlève les caractères \r ou \r\n en fin de ligne pour chaque string contenue dans listName ''' 161 newList = [] 162 for oneLine in listName: 163 if oneLine.endswith("\r\n"): 164 oneLine = oneLine[0:(len(oneLine)-2)] 165 if oneLine.endswith("\n"): 166 oneLine = oneLine[0:(len(oneLine)-1)] 167 if len(oneLine) >0: 168 newList.append(oneLine) 169 return newList 170 171 172 173 def readFileLines(filename): 174 ''' Lit le fichier filename (fichier texte), et stocke chacune de ses lignes dans la <list> newList ''' 175 if os.path.exists(filename): 176 oneStringList = [] 177 with open(filename, 'r') as myFile: 178 oneStringList = myFile.readlines() 179 newList = removeRNFromListe(oneStringList) 180 return newList 181 else: 182 return ("Le fichier "+filename+" n'existe pas!") 183 184 185 186 def readConfFile(): 187 ''' Lit le fichier /home/user/.pyFC/.pyFC.conf et 188 stocke son contenu ligne par ligne dans keyFilepathList ''' 189 global keyFilepathList 190 setConfFileAccess(True) 191 keyFilepathList = readFileLines(pfcConfFile) 192 setConfFileAccess(False) 193 194 195 196 def print4(message): 197 ''' Simple fonction print() affichant une ligne avant le message et deux lignes après ''' 198 print() 199 print(message) 200 print() 201 print() 202 203 204 205 def createKeyFiles(): 206 ''' Permet de créer les 5 fichiers clés (fichiers 'binaires') contenant nbBytes générés aléatoirement. ''' 207 global pfcConfFile 208 global pfcDir 209 global keyFilepathList 210 print("Création d'un nouveau jeu de clés de chiffrement. Cela peut prendre un moment...") 211 pathToScript = os.path.dirname(os.path.realpath(sys.argv[0])) 212 213 # Création de 5 arborescences contenant 28 niveaux de répertoires 214 # Chaque fichier clé sera généré dans le répertoire le plus loin de la racine (niveau 28) 215 for keyIndex in range(5): 216 for rep in range(28): 217 newrepName = '/.' 218 rangeSize = 3 219 if rep == 0: 220 newrepName += str(keyIndex+1) 221 rangeSize = 2; 222 for _ in range(rangeSize): 223 newrepName += random.choice(string.digits+string.ascii_letters) 224 pathToScript += newrepName 225 os.mkdir(pathToScript) 226 os.chmod(pathToScript, 0o774) 227 nbBytes = 100*(keyIndex+1)*(2**20) 228 myBytes = os.urandom(nbBytes) 229 oneFileName = pathToScript+'/.key'+str(keyIndex+1) 230 with open(oneFileName, 'wb') as keyFile: # On écrit les 5 fichiers 'clé' 231 keyFile.write(myBytes) 232 print("Fichier key"+str(keyIndex+1), "créé") 233 pathToScript = os.path.dirname(os.path.realpath(sys.argv[0])) 234 keyFilepathList.append(oneFileName) # On mémorise le chemin vers chaque clé 235 236 print() 237 print("Les 5 nouvelles clés de chiffrement ont été créées. Pour des raisons de sécurité, il est") 238 print("préférable de placer ces fichiers clés ailleurs que dans le répertoire .../pyFile") 239 print("Néanmoins, le programme fonctionnera correctement si vous n'entrez rien (simple appui sur [ENTER].") 240 print("Dans ce cas, les fichiers clés resteront simplement dans .../pyFile") 241 print() 242 print("Pour la ligne ci-dessous, si vous êtes sous Windows, veillez à") 243 print("remplacer les \ par des / dans la définition du chemin.") 244 print() 245 246 newPathStr = input("Entrez le chemin où sera installé le nouveau jeu de clés : ") 247 if len(newPathStr) > 0: 248 while not os.path.exists(newPathStr): 249 print(newPathStr,"n'est pas un répertoire valide !") 250 newPathStr = input("Entrez le chemin où sera installé le nouveau jeu de clé : ") 251 print() 252 if '/' in newPathStr[-1]: # Pour éliminer le / final si présent 253 newPathStr = newPathStr[0:len(newPathStr)-1] 254 255 # Déplacement des clés vers leur nouveau répertoire et M.A.J de keyFilepathList 256 for nindex in range(5): 257 end = len(keyFilepathList[nindex])-141 258 print(keyFilepathList[nindex][0:end]) 259 print() 260 print("Déplacement du fichier key"+str(nindex)) 261 shutil.move(keyFilepathList[nindex][0:end], newPathStr) 262 keyFilepathList[nindex] = newPathStr+keyFilepathList[nindex][end-5:-1]+str(nindex+1) 263 print() 264 265 # Création de /home/user/.pyFC si nécessaire & gestion des droits... 266 if not os.path.exists(pfcDir): 267 os.mkdir(pfcDir) 268 os.chmod(pfcDir, 0o774) # On met les droits de lecture/écriture sur le répertoire 269 if os.path.exists(pfcConfFile): 270 os.chmod(pfcConfFile, 0o774) # On met les droits de lecture/écriture sur le fichier conf 271 os.remove(pfcConfFile) # Puis on efface le fichier existant (obsolète) 272 273 for nindex in range(5): 274 with open(pfcConfFile, 'a') as confFile: # On reporte keyFilepathList dans pyFC.conf 275 confFile.write(keyFilepathList[nindex]+'\r\n') 276 277 # La configuration est maintenant écrite dans /home/user/.pyFC/.pyFC.conf, 278 # On va lire la configuration pour protéger les répertoires qui contiennent les clés 279 readConfFile() 280 # on protège les répertoires des clés en supprimant les droits de lecture de ces répertoires 281 setKeyfilesAccess(False) 282 print4("Le nouveau jeu de clés est maintenant activé") 283 284 285 def printUsage(): 286 ''' Affiche l'aide, le 'mode d'emploi' de pyFC ''' 287 print() 288 print("Utilisation :") 289 print("pyFC.py --> affiche ce mode d'emploi") 290 print("pyFC.py -help --> affiche ce mode d'emploi") 291 print("pyFC.py -init --> pour initialiser pyFC avec un nouveau jeu de clé de chiffrement") 292 print("pyFC.py -e filename --> pour chiffrer (-e --> encrypt) le fichier nommé 'filename'") 293 print("pyFC.py -e dirname --> pour chiffrer (-e --> encrypt) le répertoire nommé 'dirname'") 294 print("pyFC.py -d filename --> pour déchiffrer (-d --> decrypt) le fichier nommé 'filename'. Ici, l'") 295 print(" argument filename peut désigner soit un fichier, soit un répertoire") 296 print(" contenant d'autres fichiers ou répertoires") 297 print("pyFC.py -showconf --> change les droits sur ~/.pyFC/.pyFC.conf pour le rendre accessible") 298 print(" --> os.chmod(0o774)") 299 print("pyFC.py -hideconf --> change les droits sur ~/.pyFC/.pyFC.conf pour le rendre inaccessible") 300 print(" --> os.chmod(0o000)") 301 print(" Attention, les arguments -showconf et -hideconf ne doivent être") 302 print(" utilisés qu'après la mise en place d'un jeu de clé valide !") 303 print() 304 print() 305 306 307 308 def XOR2Arrays(bytesArray1, bytesArray2): 309 ''' Effectue un XOR byte à byte sur les 2 tableaux de bytes transmis, 310 puis retourne le bytearray qui en resulte ''' 311 return bytearray(map(ord, ''.join(chr(a ^ b) for a,b in zip(bytesArray1, bytesArray2)))) 312 313 314 315 def setCryptoBytes(mode, fileLength, offsetIntArray): 316 ''' Cette fonction permet de créer un tableau de bytes qui sera utilisé pour 317 le chiffrement/déchiffrement du fichier à traiter ''' 318 cryptoArray = [] 319 with open(keyFilepathList[0], 'rb') as currentKeyFile1: 320 if not 'decryptData' in mode: 321 currentKeyFile1.seek(10000 + 29*(fileLength % 9999)) 322 byteArrayOff11 = currentKeyFile1.read(4) 323 currentKeyFile1.seek(100000 + 1151*(fileLength % 5432)) 324 byteArrayOff52 = currentKeyFile1.read(4) 325 if not 'decryptOffset' in mode: 326 currentKeyFile1.seek(offsetIntArray[0]) 327 byteArrayData1 = currentKeyFile1.read(fileLength) 328 with open(keyFilepathList[1], 'rb') as currentKeyFile2: 329 if not 'decryptData' in mode: 330 currentKeyFile2.seek(20000 + 113*(fileLength % 8888)) 331 byteArrayOff12 = currentKeyFile2.read(4) 332 currentKeyFile2.seek(30000 + 229*(fileLength % 7777)) 333 byteArrayOff21 = currentKeyFile2.read(4) 334 if not 'decryptOffset' in mode: 335 currentKeyFile2.seek(offsetIntArray[1]) 336 byteArrayData2 = currentKeyFile2.read(fileLength) 337 with open(keyFilepathList[2], 'rb') as currentKeyFile3: 338 if not 'decryptData' in mode: 339 currentKeyFile3.seek(40000 + 349*(fileLength % 6666)) 340 byteArrayOff22 = currentKeyFile3.read(4) 341 currentKeyFile3.seek(50000 + 463*(fileLength % 5555)) 342 byteArrayOff31 = currentKeyFile3.read(4) 343 if not 'decryptOffset' in mode: 344 currentKeyFile3.seek(offsetIntArray[2]) 345 byteArrayData3 = currentKeyFile3.read(fileLength) 346 with open(keyFilepathList[3], 'rb') as currentKeyFile4: 347 if not 'decryptData' in mode: 348 currentKeyFile4.seek(60000 + 601*(fileLength % 4444)) 349 byteArrayOff32 = currentKeyFile4.read(4) 350 currentKeyFile4.seek(70000 + 733*(fileLength % 3333)) 351 byteArrayOff41 = currentKeyFile4.read(4) 352 if not 'decryptOffset' in mode: 353 currentKeyFile4.seek(offsetIntArray[3]) 354 byteArrayData4 = currentKeyFile4.read(fileLength) 355 with open(keyFilepathList[4], 'rb') as currentKeyFile5: 356 if not 'decryptData' in mode: 357 currentKeyFile5.seek(80000 + 863*(fileLength % 2222)) 358 byteArrayOff42 = currentKeyFile5.read(4) 359 currentKeyFile5.seek(90000 + 1013*(fileLength % 1111)) 360 byteArrayOff51 = currentKeyFile5.read(4) 361 if not 'decryptOffset' in mode: 362 currentKeyFile5.seek(offsetIntArray[4]) 363 byteArrayData5 = currentKeyFile5.read(fileLength) 364 365 if not 'decryptData' in mode: 366 cryptoArray.append(byteArrayOff11) 367 cryptoArray.append(byteArrayOff12) 368 cryptoArray.append(byteArrayOff21) 369 cryptoArray.append(byteArrayOff22) 370 cryptoArray.append(byteArrayOff31) 371 cryptoArray.append(byteArrayOff32) 372 cryptoArray.append(byteArrayOff41) 373 cryptoArray.append(byteArrayOff42) 374 cryptoArray.append(byteArrayOff51) 375 cryptoArray.append(byteArrayOff52) 376 if not 'decryptOffset' in mode: 377 cryptoArray.append(byteArrayData1) 378 cryptoArray.append(byteArrayData2) 379 cryptoArray.append(byteArrayData3) 380 cryptoArray.append(byteArrayData4) 381 cryptoArray.append(byteArrayData5) 382 return cryptoArray 383 384 385 386 def encrypt(savedName, filesAsByteArray, fileIndex, nbSlices): 387 ''' Fonction qui permet de procéder au chiffrement du tableau de bytes 388 'filesAsByteArray' et de le sauver sous le nom savedName ''' 389 setKeyfilesAccess(True) 390 offsetIntArray = [] 391 offsetBytesArray = [] 392 393 # ici, on créé le tableau d'offsets 394 # On aura toujours len(filesAsByteArray) < keyFileSize (donc < 100 MBytes) 395 for index in range(5): 396 intOffset = secrets.randbelow(100*(index+1)*(2**20)-len(filesAsByteArray)) 397 byte3 = intOffset >> 24 398 byte2 = (intOffset - byte3*(256**3)) >> 16 399 byte1 = (intOffset - byte3*(256**3) - byte2*(256**2)) >> 8 400 byte0 = (intOffset - byte3*(256**3) - byte2*(256**2) - byte1*256) 401 bytesList = [byte0, byte2, byte3, byte1] 402 offsetIntArray.append(intOffset) # offsetIntArray contient les offsets X au format integer normal 403 offsetBytesArray.append(bytearray(bytesList)) # offsetBytesArray contient les offsets X au format 0231 404 405 # On va créer le byteArray à partir duquel on va chiffrer les offsets et les données 406 cryptoArray = setCryptoBytes('encrypt', len(filesAsByteArray), offsetIntArray) 407 408 # On procède au chiffrement des offsets 409 headerXOffset = [] 410 headerXOffset.append(XOR2Arrays(XOR2Arrays(offsetBytesArray[0], cryptoArray[0]), cryptoArray[1])) 411 headerXOffset.append(XOR2Arrays(XOR2Arrays(offsetBytesArray[1], cryptoArray[2]), cryptoArray[3])) 412 headerXOffset.append(XOR2Arrays(XOR2Arrays(offsetBytesArray[2], cryptoArray[4]), cryptoArray[5])) 413 headerXOffset.append(XOR2Arrays(XOR2Arrays(offsetBytesArray[3], cryptoArray[6]), cryptoArray[7])) 414 headerXOffset.append(XOR2Arrays(XOR2Arrays(offsetBytesArray[4], cryptoArray[8]), cryptoArray[9])) 415 416 # On procède au chiffrement des données du fichier 417 print("Tranche "+str(fileIndex+1)+"/"+str(nbSlices)+":") 418 print("--> Chiffrement clé 1/5") 419 tempData1 = XOR2Arrays(filesAsByteArray, cryptoArray[10]) 420 print("--> Chiffrement clé 2/5") 421 tempData2 = XOR2Arrays(tempData1, cryptoArray[11]) 422 print("--> Chiffrement clé 3/5") 423 tempData3 = XOR2Arrays(tempData2, cryptoArray[12]) 424 print("--> Chiffrement clé 4/5") 425 tempData4 = XOR2Arrays(tempData3, cryptoArray[13]) 426 print("--> Chiffrement clé 5/5") 427 finalData = XOR2Arrays(tempData4, cryptoArray[14]) 428 429 # On sauve le fichier chiffré 430 with open(savedName, 'wb') as treatedFile: 431 for oneOffset in headerXOffset: 432 treatedFile.write(oneOffset) 433 treatedFile.write(finalData) 434 print("Chiffrement terminé -> Création du fichier " + savedName ) 435 print() 436 setKeyfilesAccess(False) 437 438 439 440 def addDirToZip(zipHandle, path, basePath=""): 441 ''' On va ici placer dans l'archive zipHandle tout le contenu du répertoire path ''' 442 basePath = basePath.rstrip("\\/") + "" 443 basePath = basePath.rstrip("\\/") 444 for root, dirs, files in os.walk(path): 445 # add dir itself (needed for empty dirs) 446 zipHandle.write(os.path.join(root, ".")) 447 # add files 448 for oneFile in files: 449 filePath = os.path.join(root, oneFile) 450 inZipPath = filePath.replace(basePath, "", 1).lstrip("\\/") 451 #print filePath + " , " + inZipPath 452 zipHandle.write(filePath, inZipPath) 453 454 455 456 def sliceAndEncrypt(filePath): 457 ''' Pour simplifier les choses au niveau de la fonction de chiffrement (encrypt(filePath)), on impose 458 que pour tout fichier à chiffrer, la taille doit être inférieure à celle de la clé de chiffement 459 la plus petite, soit 100MBytes (100 * 2**20). Si le fichier à chiffrer est de taille supérieure, 460 on va alors ici le découper en plusieurs tranches de tailles ~ équivalentes et inférieures à cette 461 limite de 100 MBytes. On chiffrera ensuite l'ensemble des fichiers obtenus 462 La variable limitSize (voir un peu plus bas après la ligne 'if proceed:') contiendra la limite de 463 taille réellement choisie ''' 464 465 print() 466 proceed = False 467 # Si filePath pointe vers un fichier, on va le zipper à partir du fichier avant le chiffrement 468 # cela permettra de ne pas avoir à se préoccuper du nom du fichier original (qui sera contenu dans le zip) 469 if os.path.isfile(filePath): 470 # On va créer le zip dans le répertoire courant (currentDir) 471 # Attention à bien avoir les droits d'écriture dans ce répertoire ! 472 simpleFilename = filePath.split('/')[-1] # Dans l'archive, on ne mettra que le nom du fichier, sans son path 473 print("Chiffrement de " +simpleFilename) 474 print() 475 print("Étape 1 : Création de l'archive principale") 476 zipHandle = zipfile.ZipFile('crypted.zip', 'w', zipfile.ZIP_DEFLATED) 477 zipHandle.write(simpleFilename) 478 zipHandle.close() 479 proceed = True 480 481 # Si filePath pointe vers un répertoire, on va le zipper afin de pouvoir le traiter comme un fichier 482 if os.path.isdir(filePath): 483 # On va créer le zip dans le répertoire courant (currentDir) 484 # Attention à bien avoir les droits d'écriture dans ce répertoire ! 485 zipHandle = zipfile.ZipFile('crypted.zip', 'w', zipfile.ZIP_DEFLATED) 486 savedCurrentDir = currentDir 487 repList = filePath.split('/') 488 fRepList = [] 489 repToGo = '' 490 proceed = True 491 492 # Si l'on veut par exemple crypter le répertoire /home/toto/Documents , on va se placer dans /home/toto de 493 # manière à se trouver à un étage 'supérieur' au répertoire 'Documents'. Ainsi, on pourra plus facilement 494 # inclure ce nom de répertoire (et uniquement lui) dans l'archive zip, qui contiendra alors le répertoire 495 #'/Documents' dans lequel on retrouvera tous ses fichiers et sous-répertoires 496 for nStr in repList: 497 if len(nStr)>0: 498 fRepList.append(nStr) 499 zipThisDir = nStr # Selon notre exemple, zipThisDir contiendrait 'Documents' 500 501 if len(fRepList) == 0: 502 proceed = False 503 print4("Erreur, vous ne pouvez pas chiffrer l'ensemble de la racine (/) ! \r\n \ 504 Sélectionnez un répertoire existant !") 505 506 if len(fRepList) == 1: 507 repToGo = '/' 508 os.chdir(repToGo) 509 print("Chiffrement de " +filePath) 510 print() 511 print("Étape 1 : Création de l'archive principale") 512 addDirToZip(zipHandle, zipThisDir) 513 zipHandle.close() 514 os.chdir(savedCurrentDir) 515 516 if len(fRepList)>1: 517 del fRepList[-1] 518 for oneDir in fRepList: 519 repToGo += '/' + oneDir 520 os.chdir(repToGo) # Selon notre exemple, on remonte ici dans le répertoire '/home/toto' 521 print("Chiffrement de " +filePath) 522 print() 523 print("Étape 1 : Création de l'archive principale") 524 addDirToZip(zipHandle, zipThisDir) # Ici, on va ajouter à l'archive zip tout le 525 zipHandle.close() # contenu de 'Documents' vu de '/home/toto' 526 os.chdir(savedCurrentDir) # On retourne ici dans le répertoire d'où l'on a appelé le script 527 528 if proceed : 529 print() 530 print("Étape 2 : Découpe et Chiffrement :") 531 filePath = currentDir+'/crypted.zip' 532 fileSize = os.path.getsize(filePath) 533 534 # On va charger le fichier à traiter, puis le découper en byteArray(s) de taille < 100MBytes si besoin 535 # On a le choix ici de la limite de taille des byteArrays (doit être impérativement < 100MBytes) 536 # Plus on abaisse cette limite, plus le chiffrement sera rapide pour les fichiers de taille supérieure 537 # En contrepartie, on aura un chiffrement en plusieurs étapes (autant que de tranches, après découpe 538 # du fichier crypted.zip) 539 limitSize = (3+int(fileSize/(15*(2**20)))) * (2**20) 540 if limitSize > (50*(2**20)): 541 limitSize = 50*(2**20) 542 print(limitSize) 543 if fileSize < limitSize: 544 nbSlices = 1 545 rawSliceSize = fileSize 546 else: 547 nbSlices = int(fileSize/limitSize) + 1 548 rawSliceSize = int(fileSize/nbSlices) + 1 549 550 filesAsByteArray = [] 551 with open(filePath, 'rb') as treatedFile: 552 for n in range(nbSlices): 553 treatedFile.seek(n*rawSliceSize) 554 filesAsByteArray.append(treatedFile.read(rawSliceSize)) 555 556 # On va maintenant chiffrer chaque byteArray, puis le sauver en tant que fichier chiffré 557 namePart = '/' + str(int(time.time())) 558 print(nbSlices) 559 for n in range(nbSlices): 560 fileExt = ".00" 561 if 9 < n < 100: 562 fileExt = ".0" 563 if 1000 > n > 99: 564 fileExt = "." 565 saveName = currentDir + namePart + fileExt + str(n) 566 encrypt(saveName, filesAsByteArray[n], n, nbSlices) 567 568 # On va supprimer le fichier crypted.zip qui n'est plus utile 569 os.remove(filePath) 570 time.sleep(2) # Petite pause avant fermeture du terminal si lancé en clic-droit depuis caja 571 572 573 574 def decrypt(filePath, nbSlices): 575 ''' Fonction qui permet de procéder au déchiffrement du fichier filePath ''' 576 if os.path.isfile(filePath): # Si filePath pointe bien vers un fichier 577 setKeyfilesAccess(True) 578 usedLength = os.path.getsize(filePath) - 20 # On retire les 20 octets d'entête qui ont été 579 headerXOffset = [] # ajouté lors du chiffrement 580 581 # On va reconstituer le byteArray à partir duquel on a chiffré les offsets 582 offsetIntArray = 0 583 cryptoArray = setCryptoBytes('decryptOffset', usedLength, offsetIntArray) 584 585 # Lecture et déchiffrement 1/2 des 5 offsets chiffrés 586 with open(filePath, 'rb') as cryptedFile: 587 off1 = cryptedFile.read(4) 588 headerXOffset.append(XOR2Arrays(XOR2Arrays(off1, cryptoArray[0]), cryptoArray[1])) 589 cryptedFile.seek(4) 590 off2 = cryptedFile.read(4) 591 headerXOffset.append(XOR2Arrays(XOR2Arrays(off2, cryptoArray[2]), cryptoArray[3])) 592 cryptedFile.seek(8) 593 off3 = cryptedFile.read(4) 594 headerXOffset.append(XOR2Arrays(XOR2Arrays(off3, cryptoArray[4]), cryptoArray[5])) 595 cryptedFile.seek(12) 596 off4 = cryptedFile.read(4) 597 headerXOffset.append(XOR2Arrays(XOR2Arrays(off4, cryptoArray[6]), cryptoArray[7])) 598 cryptedFile.seek(16) 599 off5 = cryptedFile.read(4) 600 headerXOffset.append(XOR2Arrays(XOR2Arrays(off5, cryptoArray[8]), cryptoArray[9])) 601 cryptedFile.seek(20) 602 cypherData = cryptedFile.read(usedLength) 603 604 # Reconstitution des offsets (Déchiffrement 2/2) 605 intOffset = [] 606 for oneHeaderOffset in headerXOffset: 607 byte0 = oneHeaderOffset[0] 608 byte2 = oneHeaderOffset[1] 609 byte3 = oneHeaderOffset[2] 610 byte1 = oneHeaderOffset[3] 611 intOffset.append(int(byte3*(256**3) + byte2*(256**2)+ byte1*256 + byte0)) 612 613 # On va reconstituer le byteArray à partir duquel on a chiffré les données 614 cryptoArray = setCryptoBytes('decryptData', usedLength, intOffset) 615 616 # On procède au déchiffrement des données 617 fileExt = filePath.split('.')[-1] 618 intFileExt = int(fileExt) 619 print("Tranche "+str(intFileExt+1)+"/"+str(nbSlices)+":") 620 print("--> Déchiffrement clé 1/5") 621 tempData1 = XOR2Arrays(cypherData, cryptoArray[4]) 622 print("--> Déchiffrement clé 2/5") 623 tempData2 = XOR2Arrays(tempData1, cryptoArray[3]) 624 print("--> Déchiffrement clé 3/5") 625 tempData3 = XOR2Arrays(tempData2, cryptoArray[2]) 626 print("--> Déchiffrement clé 4/5") 627 tempData4 = XOR2Arrays(tempData3, cryptoArray[1]) 628 print("--> Déchiffrement clé 5/5") 629 finalData = XOR2Arrays(tempData4, cryptoArray[0]) 630 631 # On sauve le fichier déchiffré 632 with open(currentDir+'/decypher.'+fileExt, 'wb') as treatedFile: 633 treatedFile.write(finalData) 634 print("Déchiffrement terminé -> Écriture du fichier " + currentDir+'/decypher.'+fileExt) 635 print() 636 setKeyfilesAccess(False) 637 return(currentDir+'/decypher.'+fileExt) # On va retourner le nom du fichier déchiffré, 638 # afin de pouvoir le ré-assembler si besoin 639 640 641 642 def getSlicesAndDecrypt(filePath): 643 ''' On va déterminer ici en combien de tranches le fichier original a été découpé avant chiffrement. 644 On devra déchiffrer chaque tranche, puis ré-assembler le tout pour reconstituer l'archive originale. 645 Dans un dernier temps, on pourra enfin décompresser l'archive ''' 646 647 print() 648 if os.path.exists(filePath): 649 print("Déchiffrement de " +filePath) 650 print() 651 repList = filePath.split('.') 652 if '000' in repList[-1]: # On s'assure que le fichier à déchiffrer possède bien une extension en .000 653 myCypherList = [] 654 myCypherList.append(filePath) 655 index = 1 656 bitContinue = True 657 while bitContinue: 658 fileExt = ".00" 659 if 9 < index < 100: 660 fileExt = ".0" 661 if 1000 > index > 99: 662 fileExt = "." 663 tryThisFile = repList[0]+fileExt+str(index) 664 index += 1 665 if os.path.exists(tryThisFile): 666 myCypherList.append(tryThisFile) # myCypherList contiendra la liste des fichiers à déchiffrer 667 else: 668 bitContinue = False 669 decypheredList = [] 670 decypheredByteArray = [] 671 for oneCryptedSlice in myCypherList: 672 decypheredList.append(decrypt(oneCryptedSlice, len(myCypherList))) 673 for oneFile in decypheredList: 674 with open(oneFile, 'rb') as decypheredSlice: 675 tmpArray = decypheredSlice.read() 676 decypheredByteArray.append(tmpArray) 677 os.remove(oneFile) 678 with open('finalFile.zip', 'wb') as finalFile: 679 for oneByteArray in decypheredByteArray: 680 finalFile.write(oneByteArray) 681 finalZip = zipfile.ZipFile('finalFile.zip', 'r') 682 try: 683 rootArcName = finalZip.namelist()[0] # On vient chercher le nom du répertoire racine contenu 684 except: # dans finalFile.zip 685 print("L'archive semble vide...") 686 print() 687 finalZip.extractall(currentDir) 688 os.remove('finalFile.zip') 689 print4("Extraction / création de " +rootArcName+ " --> Déchiffrement terminé") 690 time.sleep(2) # Petite pause avant fermeture du terminal si lancé en clic-droit depuis caja 691 else: 692 print4(filePath+" n'est pas un fichier valide pour déchiffrement !") 693 time.sleep(2) # Petite pause avant fermeture du terminal si lancé en clic-droit depuis caja 694 695 696 697 698 ###################### Lancement du programme principal ###################### 699 # 700 if __name__ == "__main__": 701 pfcDir = os.path.expanduser('~')+'/.pyFC' 702 pfcConfFile = pfcDir+'/.pyFC.conf' 703 currentDir = os.getcwd() 704 keyFilepathList = [] 705 if len(sys.argv) == 1: 706 printUsage() 707 if len(sys.argv) == 2: 708 foundBit2 = False 709 if '-help' in (sys.argv[1]): 710 foundBit2 = True 711 printUsage() 712 if '-init' in (sys.argv[1]): 713 foundBit2 = True 714 print("Cette opération va générer un nouveau jeu de clés de chiffrement.") 715 strOK = input("Voulez-vous vraiment continuer ? (Abandon si différent de OK) : ") 716 if len(strOK)==2 and 'OK' in strOK: 717 createKeyFiles() 718 else: 719 print4("Abandon...") 720 if '-showconf' in (sys.argv[1]): 721 foundBit2 = True 722 readConfFile() 723 setConfFileAccess(True) 724 setKeyfilesAccess(True) 725 print4("Configuration et arborescence de clés accessibles.") 726 if '-hideconf' in (sys.argv[1]): 727 foundBit2 = True 728 readConfFile() 729 setConfFileAccess(False) 730 setKeyfilesAccess(False) 731 print4("Configuration et arborescence de clés protégées.") 732 if not foundBit2: # Cas où l'on oublie par exemple de fournir un chemin pour le chiffrement/déchiffrement 733 printUsage() 734 if len(sys.argv) == 3: 735 ed = False 736 badFilePath = False 737 if '-e' in (sys.argv[1]) or '-d' in (sys.argv[1]): 738 ed = True 739 if len(sys.argv[2]) > 1: 740 if os.path.exists(sys.argv[2]): # On va ici traiter le chiffrement ou le déchiffrement 741 readConfFile() # On lit le fichier conf pour accéder aux chemins des fichiers clés 742 if '-e' in (sys.argv[1]): 743 sliceAndEncrypt(sys.argv[2]) 744 if '-d' in (sys.argv[1]): 745 getSlicesAndDecrypt(sys.argv[2]) 746 else: 747 badFilePath = True 748 if not ed: 749 # Erreur sur argument -e ou -d 750 print4("Erreur : commande incompréhensible !") 751 printUsage() 752 if badFilePath: 753 # Erreur sur chemin vers fichier ou répertoire passé en argument 754 print4("Erreur : la chaine à traiter n'existe pas, n'est ni un fichier ni un répertoire !") 755 if len(sys.argv) > 3: # Trop de paramètres passés en argument ! 756 print4("Erreur : trop de paramètres passés en argument !") 757 printUsage() 758