Cryptographie avec Python - Guide rapide
La cryptographie est l'art de la communication entre deux utilisateurs via des messages codés. La science de la cryptographie a émergé avec le motif fondamental d'assurer la sécurité des messages confidentiels transférés d'une partie à une autre.
La cryptographie est définie comme l'art et la science de dissimuler le message pour introduire la confidentialité et le secret reconnus dans la sécurité de l'information.
Terminologies de la cryptographie
Les termes fréquemment utilisés en cryptographie sont expliqués ici -
Texte brut
Le message en texte brut est le texte qui est lisible et peut être compris par tous les utilisateurs. Le texte brut est le message qui subit la cryptographie.
Texte chiffré
Le texte chiffré est le message obtenu après l'application de la cryptographie sur du texte brut.
Chiffrement
Le processus de conversion de texte brut en texte chiffré est appelé cryptage. Il est également appelé encodage.
Décryptage
Le processus de conversion du texte chiffré en texte brut est appelé déchiffrement. Il est également appelé décodage.
Le diagramme ci-dessous montre une illustration du processus complet de cryptographie -
Caractéristiques de la cryptographie moderne
Les caractéristiques de base de la cryptographie moderne sont les suivantes -
Il fonctionne sur des séquences de bits.
Il utilise des algorithmes mathématiques pour sécuriser les informations.
Il oblige les parties intéressées par un canal de communication sécurisé à respecter la confidentialité.
Le cryptage à double force, également appelé cryptage multiple, est le processus de cryptage d'un texte déjà crypté une ou plusieurs fois, avec le même algorithme / modèle ou un autre.
Les autres noms pour le chiffrement à double force incluent le chiffrement en cascade ou le chiffrement en cascade.
Niveaux de chiffrement à double force
Le cryptage à double force comprend différents niveaux de cryptage qui sont expliqués ci-dessous -
Première couche de cryptage
Le texte chiffré est généré à partir du message lisible d'origine à l'aide d'algorithmes de hachage et de clés symétriques. Les clés symétriques ultérieures sont chiffrées à l'aide de clés asymétriques. La meilleure illustration de ce modèle consiste à combiner le condensé de hachage du texte chiffré dans une capsule. Le récepteur calculera d'abord le condensé puis décryptera le texte afin de vérifier que le texte n'est pas altéré entre les deux.
Deuxième couche de cryptage
La deuxième couche de cryptage est le processus d'ajout d'une couche supplémentaire pour chiffrer le texte avec un algorithme identique ou différent. Habituellement, un mot de passe symétrique de 32 bits est utilisé pour la même chose.
Troisième couche de cryptage
Dans ce processus, la capsule cryptée est transmise via une connexion SSL / TLS au partenaire de communication.
Le schéma suivant montre le processus de double cryptage en images -
Cryptographie hybride
La cryptographie hybride est le processus consistant à utiliser plusieurs chiffrements de différents types ensemble en incluant les avantages de chacun des chiffrements. Il existe une approche courante qui est généralement suivie pour générer une clé secrète aléatoire pour un chiffrement symétrique, puis crypter cette clé via une cryptographie à clé asymétrique.
En raison de ce modèle, le message d'origine lui-même est chiffré à l'aide du chiffrement symétrique, puis à l'aide d'une clé secrète. Le destinataire après avoir reçu le message déchiffre le message en utilisant d'abord la clé secrète, en utilisant sa propre clé privée, puis utilise la clé spécifiée pour déchiffrer le message.
Python est un langage de script open source qui est de haut niveau, interprété, interactif et orienté objet. Il est conçu pour être hautement lisible. La syntaxe du langage Python est facile à comprendre et utilise fréquemment des mots-clés anglais.
Caractéristiques du langage Python
Python fournit les principales fonctionnalités suivantes -
Interprété
Python est traité au moment de l'exécution à l'aide de l'interpréteur. Il n'est pas nécessaire de compiler un programme avant son exécution. Il est similaire à PERL et PHP.
Orienté objet
Python suit le style et les modèles de conception orientés objet. Il comprend une définition de classe avec diverses fonctionnalités telles que l'encapsulation et le polymorphisme.
Points clés du langage Python
Les points clés du langage de programmation Python sont les suivants -
Il comprend une programmation et des méthodes fonctionnelles et structurées ainsi que des méthodes de programmation orientées objet.
Il peut être utilisé comme langage de script ou comme langage de programmation.
Il inclut la collecte automatique des ordures.
Il comprend des types de données dynamiques de haut niveau et prend en charge diverses vérifications de types dynamiques.
Python inclut une fonctionnalité d'intégration avec C, C ++ et des langages comme Java.
Le lien de téléchargement pour le langage Python est le suivant - www.python.org/downloads Il comprend des packages pour divers systèmes d'exploitation tels que les distributions Windows, MacOS et Linux.
Chaînes Python
La déclaration de base des chaînes est présentée ci-dessous -
str = 'Hello World!'
Listes Python
Les listes de python peuvent être déclarées comme des types de données composés, séparés par des virgules et placés entre crochets ([]).
list = [ 'abcd', 786 , 2.23, 'john', 70.2 ]
tinylist = [123, 'john']
Tuples Python
Un tuple est un type de données dynamique de Python qui consiste en un nombre de valeurs séparées par des virgules. Les tuples sont entre parenthèses.
tinytuple = (123, 'john')
Dictionnaire Python
Le dictionnaire Python est un type de table de hachage. Une clé de dictionnaire peut être presque n'importe quel type de données de Python, qui sont généralement des nombres ou des chaînes.
tinydict = {'name': 'omkar','code':6734, 'dept': 'sales'}
Paquets de cryptographie
Python inclut un package appelé cryptographie qui fournit des recettes et des primitives cryptographiques. Il prend en charge Python 2.7, Python 3.4+ et PyPy 5.3+. L'installation de base du package de cryptographie est réalisée via la commande suivante -
pip install cryptography
Il existe différents packages avec à la fois des recettes de haut niveau et des interfaces de bas niveau vers des algorithmes cryptographiques courants tels que symmetric ciphers, message digests et key derivation functions.
Tout au long de ce tutoriel, nous utiliserons divers packages de Python pour la mise en œuvre d'algorithmes cryptographiques.
Le chapitre précédent vous a donné un aperçu de l'installation de Python sur votre ordinateur local. Dans ce chapitre, vous apprendrez en détail le chiffrement inversé et son codage.
Algorithme de chiffrement inversé
L'algorithme de chiffrement inversé possède les caractéristiques suivantes -
Le chiffrement inversé utilise un modèle d'inversion de la chaîne de texte brut pour la convertir en texte chiffré.
Le processus de cryptage et de décryptage est le même.
Pour déchiffrer le texte chiffré, l'utilisateur doit simplement inverser le texte chiffré pour obtenir le texte brut.
Inconvénient
L'inconvénient majeur du chiffrement inversé est qu'il est très faible. Un pirate informatique peut facilement casser le texte chiffré pour obtenir le message d'origine. Par conséquent, le chiffrement inversé n'est pas considéré comme une bonne option pour maintenir un canal de communication sécurisé.
Exemple
Prenons un exemple où la déclaration This is program to explain reverse cipherdoit être implémenté avec un algorithme de chiffrement inversé. Le code python suivant utilise l'algorithme pour obtenir la sortie.
message = 'This is program to explain reverse cipher.'
translated = '' #cipher text is stored in this variable
i = len(message) - 1
while i >= 0:
translated = translated + message[i]
i = i - 1
print(“The cipher text is : “, translated)
Production
Vous pouvez voir le texte inversé, c'est-à-dire la sortie comme indiqué dans l'image suivante -
Explication
Le texte brut est stocké dans le message variable et la variable traduite est utilisée pour stocker le texte chiffré créé.
La longueur du texte brut est calculée en utilisant for boucle et avec l'aide de index number. Les caractères sont stockés dans la variable de texte chiffrétranslated qui est imprimé dans la dernière ligne.
Dans le dernier chapitre, nous avons traité du chiffrement inversé. Ce chapitre décrit en détail le chiffre de César.
Algorithme de César Cipher
L'algorithme du chiffre de César possède les caractéristiques suivantes -
La technique de chiffrement César est la méthode simple et facile de la technique de chiffrement.
C'est un simple type de chiffrement de substitution.
Chaque lettre de texte brut est remplacée par une lettre avec un nombre fixe de positions vers le bas avec l'alphabet.
Le diagramme suivant illustre le fonctionnement de l'implémentation de l'algorithme de chiffrement de César -
La mise en œuvre du programme de l'algorithme de chiffrement César est la suivante -
def encrypt(text,s):
result = ""
# transverse the plain text
for i in range(len(text)):
char = text[i]
# Encrypt uppercase characters in plain text
if (char.isupper()):
result += chr((ord(char) + s-65) % 26 + 65)
# Encrypt lowercase characters in plain text
else:
result += chr((ord(char) + s - 97) % 26 + 97)
return result
#check the above function
text = "CEASER CIPHER DEMO"
s = 4
print "Plain Text : " + text
print "Shift pattern : " + str(s)
print "Cipher: " + encrypt(text,s)
Production
Vous pouvez voir le chiffre César, c'est la sortie comme indiqué dans l'image suivante -
Explication
Le caractère de texte brut est parcouru un par un.
Pour chaque caractère du texte brut donné, transformez le caractère donné selon la règle en fonction de la procédure de cryptage et de décryptage du texte.
Une fois les étapes suivies, une nouvelle chaîne est générée, appelée texte chiffré.
Piratage de l'algorithme de chiffrement César
Le texte chiffré peut être piraté avec diverses possibilités. L'une de ces possibilités estBrute Force Technique,ce qui implique d'essayer toutes les clés de déchiffrement possibles. Cette technique ne demande pas beaucoup d'efforts et est relativement simple pour un hacker.
La mise en œuvre du programme pour le piratage de l'algorithme de chiffrement César est la suivante -
message = 'GIEWIVrGMTLIVrHIQS' #encrypted message
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for key in range(len(LETTERS)):
translated = ''
for symbol in message:
if symbol in LETTERS:
num = LETTERS.find(symbol)
num = num - key
if num < 0:
num = num + len(LETTERS)
translated = translated + LETTERS[num]
else:
translated = translated + symbol
print('Hacking key #%s: %s' % (key, translated))
Considérez le texte chiffré chiffré dans l'exemple précédent. Ensuite, la sortie avec les méthodes de piratage possibles avec la clé et en utilisant la technique d'attaque par force brute est la suivante -
Jusqu'à présent, vous avez appris les algorithmes de chiffrement inversé et de chiffrement César. Parlons maintenant de l'algorithme ROT13 et de son implémentation.
Explication de l'algorithme ROT13
Le chiffre ROT13 fait référence à la forme abrégée Rotate by 13 places. C'est un cas particulier de César Cipher dans lequel le décalage est toujours de 13. Chaque lettre est décalée de 13 places pour crypter ou décrypter le message.
Exemple
Le diagramme suivant explique le processus de l'algorithme ROT13 en images -
Code de programme
La mise en œuvre du programme de l'algorithme ROT13 est la suivante -
from string import maketrans
rot13trans = maketrans('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm')
# Function to translate plain text
def rot13(text):
return text.translate(rot13trans)
def main():
txt = "ROT13 Algorithm"
print rot13(txt)
if __name__ == "__main__":
main()
Vous pouvez voir la sortie ROT13 comme indiqué dans l'image suivante -
Inconvénient
L'algorithme ROT13 utilise 13 décalages. Par conséquent, il est très facile de décaler les caractères dans le sens inverse pour décrypter le texte chiffré.
Analyse de l'algorithme ROT13
L'algorithme de chiffrement ROT13 est considéré comme un cas particulier de César Cipher. Ce n'est pas un algorithme très sécurisé et peut être cassé facilement avec une analyse de fréquence ou en essayant simplement 25 touches possibles alors que ROT13 peut être cassé en décalant 13 places. Par conséquent, il n'inclut aucune utilisation pratique.
Le chiffrement de transposition est un algorithme cryptographique dans lequel l'ordre des alphabets dans le texte en clair est réorganisé pour former un texte chiffré. Dans ce processus, les alphabets de texte brut réels ne sont pas inclus.
Exemple
Un exemple simple de chiffrement de transposition est columnar transposition cipheroù chaque caractère du texte brut est écrit horizontalement avec une largeur d'alphabet spécifiée. Le chiffrement est écrit verticalement, ce qui crée un texte chiffré entièrement différent.
Considérez le texte brut hello world, et appliquons la technique de transposition en colonne simple comme indiqué ci-dessous
Les caractères de texte brut sont placés horizontalement et le texte chiffré est créé au format vertical comme : holewdlo lr. Maintenant, le récepteur doit utiliser la même table pour déchiffrer le texte chiffré en texte brut.
Code
Le code de programme suivant illustre l'implémentation de base de la technique de transposition en colonnes -
def split_len(seq, length):
return [seq[i:i + length] for i in range(0, len(seq), length)]
def encode(key, plaintext):
order = {
int(val): num for num, val in enumerate(key)
}
ciphertext = ''
for index in sorted(order.keys()):
for part in split_len(plaintext, len(key)):
try:ciphertext += part[order[index]]
except IndexError:
continue
return ciphertext
print(encode('3214', 'HELLO'))
Explication
Utilisation de la fonction split_len(), nous pouvons diviser les caractères de texte brut, qui peuvent être placés au format colonne ou ligne.
encode La méthode permet de créer un texte chiffré avec une clé spécifiant le nombre de colonnes et imprime le texte chiffré en lisant des caractères dans chaque colonne.
Production
Le code de programme pour l'implémentation de base de la technique de transposition en colonnes donne le résultat suivant -
Note- Les cryptanalystes ont observé une amélioration significative de la sécurité cryptographique lorsque la technique de transposition est effectuée. Ils ont également noté que le rechiffrement du texte chiffré à l'aide du même chiffrement de transposition crée une meilleure sécurité.
Dans le chapitre précédent, nous avons appris le chiffrement de transposition. Dans ce chapitre, parlons de son cryptage.
Pyperclip
L'utilisation principale de pyperclipplugin en langage de programmation Python consiste à effectuer un module multiplateforme pour copier et coller du texte dans le presse-papiers. Vous pouvez installer pythonpyperclip module en utilisant la commande comme indiqué
pip install pyperclip
Si l'exigence existe déjà dans le système, vous pouvez voir la sortie suivante -
Code
Le code python pour chiffrer le chiffrement de transposition dans lequel pyperclip est le module principal est comme indiqué ci-dessous -
import pyperclip
def main():
myMessage = 'Transposition Cipher'
myKey = 10
ciphertext = encryptMessage(myKey, myMessage)
print("Cipher Text is")
print(ciphertext + '|')
pyperclip.copy(ciphertext)
def encryptMessage(key, message):
ciphertext = [''] * key
for col in range(key):
position = col
while position < len(message):
ciphertext[col] += message[position]
position += key
return ''.join(ciphertext) #Cipher text
if __name__ == '__main__':
main()
Production
Le code de programme pour crypter le chiffre de transposition dans lequel pyperclip est le module principal donne la sortie suivante -
Explication
La fonction main() appelle le encryptMessage() qui comprend la procédure de fractionnement des caractères en utilisant len fonction et les itérer dans un format en colonnes.
La fonction principale est initialisée à la fin pour obtenir la sortie appropriée.
Dans ce chapitre, vous apprendrez la procédure pour déchiffrer le chiffrement de transposition.
Code
Observez le code suivant pour une meilleure compréhension du déchiffrement d'un chiffrement de transposition. Le texte chiffré du messageTransposition Cipher avec clé comme 6 est récupéré comme Toners raiCntisippoh.
import math, pyperclip
def main():
myMessage= 'Toners raiCntisippoh'
myKey = 6
plaintext = decryptMessage(myKey, myMessage)
print("The plain text is")
print('Transposition Cipher')
def decryptMessage(key, message):
numOfColumns = math.ceil(len(message) / key)
numOfRows = key
numOfShadedBoxes = (numOfColumns * numOfRows) - len(message)
plaintext = float('') * numOfColumns
col = 0
row = 0
for symbol in message:
plaintext[col] += symbol
col += 1
if (col == numOfColumns) or (col == numOfColumns - 1 and row >= numOfRows - numOfShadedBoxes):
col = 0 row += 1 return ''.join(plaintext)
if __name__ == '__main__':
main()
Explication
Le texte chiffré et la clé mentionnée sont les deux valeurs prises comme paramètres d'entrée pour décoder ou déchiffrer le texte chiffré en technique inverse en plaçant les caractères dans un format de colonne et en les lisant de manière horizontale.
Vous pouvez placer des lettres dans un format de colonne et ensuite les combiner ou les concaténer en utilisant le morceau de code suivant -
for symbol in message:
plaintext[col] += symbol
col += 1
if (col == numOfColumns) or (col == numOfColumns - 1 and row >= numOfRows - numOfShadedBoxes):
col = 0
row += 1
return ''.join(plaintext)
Production
Le code de programme pour déchiffrer le chiffrement de transposition donne la sortie suivante -
En Python, il est possible de crypter et décrypter des fichiers avant de les transmettre à un canal de communication. Pour cela, vous devrez utiliser le pluginPyCrypto. Vous pouvez installer ce plugin en utilisant la commande donnée ci-dessous.
pip install pycrypto
Code
Le code du programme pour crypter le fichier avec le protecteur de mot de passe est mentionné ci-dessous -
# =================Other Configuration================
# Usages :
usage = "usage: %prog [options] "
# Version
Version="%prog 0.0.1"
# ====================================================
# Import Modules
import optparse, sys,os
from toolkit import processor as ps
def main():
parser = optparse.OptionParser(usage = usage,version = Version)
parser.add_option(
'-i','--input',type = 'string',dest = 'inputfile',
help = "File Input Path For Encryption", default = None)
parser.add_option(
'-o','--output',type = "string",dest = 'outputfile',
help = "File Output Path For Saving Encrypter Cipher",default = ".")
parser.add_option(
'-p','--password',type = "string",dest = 'password',
help = "Provide Password For Encrypting File",default = None)
parser.add_option(
'-p','--password',type = "string",dest = 'password',
help = "Provide Password For Encrypting File",default = None)
(options, args)= parser.parse_args()
# Input Conditions Checkings
if not options.inputfile or not os.path.isfile(options.inputfile):
print " [Error] Please Specify Input File Path"
exit(0)
if not options.outputfile or not os.path.isdir(options.outputfile):
print " [Error] Please Specify Output Path"
exit(0)
if not options.password:
print " [Error] No Password Input"
exit(0)
inputfile = options.inputfile
outputfile = os.path.join(
options.outputfile,os.path.basename(options.inputfile).split('.')[0]+'.ssb')
password = options.password
base = os.path.basename(inputfile).split('.')[1]
work = "E"
ps.FileCipher(inputfile,outputfile,password,work)
return
if __name__ == '__main__':
main()
Vous pouvez utiliser la commande suivante pour exécuter le processus de cryptage avec le mot de passe -
python pyfilecipher-encrypt.py -i file_path_for_encryption -o output_path -p password
Production
Vous pouvez observer la sortie suivante lorsque vous exécutez le code donné ci-dessus -
Explication
Les mots de passe sont générés à l'aide de l'algorithme de hachage MD5 et les valeurs sont stockées dans des fichiers de sauvegarde simplement sûrs dans le système Windows, qui comprend les valeurs affichées ci-dessous -
Dans ce chapitre, parlons du décryptage des fichiers en cryptographie à l'aide de Python. Notez que pour le processus de décryptage, nous suivrons la même procédure, mais au lieu de spécifier le chemin de sortie, nous nous concentrerons sur le chemin d'entrée ou le fichier nécessaire qui est crypté.
Code
Ce qui suit est un exemple de code pour déchiffrer des fichiers en cryptographie à l'aide de Python -
#!/usr/bin/python
# ---------------- READ ME ---------------------------------------------
# This Script is Created Only For Practise And Educational Purpose Only
# This Script Is Created For http://bitforestinfo.blogspot.in
# This Script is Written By
#
#
##################################################
######## Please Don't Remove Author Name #########
############### Thanks ###########################
##################################################
#
#
# =================Other Configuration================
# Usages :
usage = "usage: %prog [options] "
# Version
Version="%prog 0.0.1"
# ====================================================
# Import Modules
import optparse, sys,os
from toolkit import processor as ps
def main():
parser = optparse.OptionParser(usage = usage,version = Version)
parser.add_option(
'-i','--input',type = 'string',dest = 'inputfile',
help = "File Input Path For Encryption", default = None)
parser.add_option(
'-o','--output',type = "string",dest = 'outputfile',
help = "File Output Path For Saving Encrypter Cipher",default = ".")
parser.add_option(
'-p','--password',type = "string",dest = 'password',
help = "Provide Password For Encrypting File",default = None)
(options, args) = parser.parse_args()
# Input Conditions Checkings
if not options.inputfile or not os.path.isfile(options.inputfile):
print " [Error] Please Specify Input File Path"
exit(0)
if not options.outputfile or not os.path.isdir(options.outputfile):
print " [Error] Please Specify Output Path"
exit(0)
if not options.password:
print " [Error] No
exit(0)
inputfile = options.inputfile
outputfile = options.outputfile
password = options.password
work = "D"
ps.FileCipher(inputfile,outputfile,password,work)
return
if __name__ == '__main__':
main()
Vous pouvez utiliser la commande suivante pour exécuter le code ci-dessus -
python pyfilecipher-decrypt.py -i encrypted_file_path -p password
Production
Vous pouvez observer le code suivant lorsque vous exécutez la commande ci-dessus -
Note - La sortie spécifie les valeurs de hachage avant le cryptage et après le décryptage, ce qui garde une note que le même fichier est crypté et que le processus a réussi.
Le codage Base64 convertit les données binaires au format texte, qui est passé par le canal de communication où un utilisateur peut gérer le texte en toute sécurité. Base64 est également appeléPrivacy enhanced Electronic mail (PEM) et est principalement utilisé dans le processus de cryptage des e-mails.
Python comprend un module appelé BASE64 qui comprend deux fonctions principales comme indiqué ci-dessous -
base64.decode(input, output) - Il décode le paramètre de valeur d'entrée spécifié et stocke la sortie décodée en tant qu'objet.
Base64.encode(input, output) - Il code le paramètre de valeur d'entrée spécifié et stocke la sortie décodée en tant qu'objet.
Programme d'encodage
Vous pouvez utiliser le morceau de code suivant pour effectuer un encodage base64 -
import base64
encoded_data = base64.b64encode("Encode this text")
print("Encoded text with base 64 is")
print(encoded_data)
Production
Le code pour l'encodage base64 vous donne la sortie suivante -
Programme de décodage
Vous pouvez utiliser le morceau de code suivant pour effectuer le décodage base64 -
import base64
decoded_data = base64.b64decode("RW5jb2RlIHRoaXMgdGV4dA==")
print("decoded text is ")
print(decoded_data)
Production
Le code pour le décodage base64 vous donne la sortie suivante -
Différence entre ASCII et base64
Vous pouvez observer les différences suivantes lorsque vous travaillez sur ASCII et base64 pour le codage des données -
Lorsque vous encodez du texte en ASCII, vous commencez par une chaîne de texte et la convertissez en une séquence d'octets.
Lorsque vous encodez des données en Base64, vous commencez par une séquence d'octets et vous la convertissez en chaîne de texte.
Inconvénient
L'algorithme Base64 est généralement utilisé pour stocker les mots de passe dans la base de données. L'inconvénient majeur est que chaque mot décodé peut être encodé facilement via n'importe quel outil en ligne et que les intrus peuvent facilement obtenir les informations.
Dans ce chapitre, comprenons le processus XOR ainsi que son codage en Python.
Algorithme
L'algorithme XOR de chiffrement et de déchiffrement convertit le texte brut au format octets ASCII et utilise la procédure XOR pour le convertir en un octet spécifié. Il offre les avantages suivants à ses utilisateurs -
- Calcul rapide
- Aucune différence marquée du côté gauche et du côté droit
- Facile à comprendre et à analyser
Code
Vous pouvez utiliser le morceau de code suivant pour effectuer le processus XOR -
def xor_crypt_string(data, key = 'awesomepassword', encode = False, decode = False):
from itertools import izip, cycle
import base64
if decode:
data = base64.decodestring(data)
xored = ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(data, cycle(key)))
if encode:
return base64.encodestring(xored).strip()
return xored
secret_data = "XOR procedure"
print("The cipher text is")
print xor_crypt_string(secret_data, encode = True)
print("The plain text fetched")
print xor_crypt_string(xor_crypt_string(secret_data, encode = True), decode = True)
Production
Le code du processus XOR vous donne la sortie suivante -
Explication
La fonction xor_crypt_string() inclut un paramètre pour spécifier le mode d'encodage et de décodage ainsi que la valeur de la chaîne.
Les fonctions de base sont prises avec des modules base64 qui suivent la procédure / opération XOR pour crypter ou décrypter le texte brut / texte chiffré.
Note - Le cryptage XOR est utilisé pour crypter les données et est difficile à craquer par la méthode de la force brute, c'est-à-dire en générant des clés de cryptage aléatoires pour correspondre au texte de cryptage correct.
Tout en utilisant la technique de chiffrement César, le cryptage et le décryptage des symboles implique la conversion des valeurs en nombres avec une simple procédure de base d'addition ou de soustraction.
Si la multiplication est utilisée pour convertir en texte chiffré, on l'appelle un wrap-aroundsituation. Considérez les lettres et les numéros associés à utiliser comme indiqué ci-dessous -
Les nombres seront utilisés pour la procédure de multiplication et la clé associée est 7. La formule de base à utiliser dans un tel scénario pour générer un chiffre multiplicatif est la suivante -
(Alphabet Number * key)mod(total number of alphabets)
Le nombre récupéré via la sortie est mappé dans le tableau mentionné ci-dessus et la lettre correspondante est considérée comme la lettre cryptée.
La fonction de modulation de base d'un chiffrement multiplicatif en Python est la suivante -
def unshift(key, ch):
offset = ord(ch) - ASC_A
return chr(((key[0] * (offset + key[1])) % WIDTH) + ASC_A)
Note- L'avantage d'un chiffrement multiplicatif est qu'il peut fonctionner avec de très grosses clés comme 8,953,851. Il faudrait un temps assez long à un ordinateur pour forcer une majorité de neuf millions de clés.
Affine Cipher est la combinaison de l'algorithme Multiplicative Cipher et Caesar Cipher. La mise en œuvre de base du chiffrement affine est comme indiqué dans l'image ci-dessous -
Dans ce chapitre, nous implémenterons le chiffrement affine en créant sa classe correspondante qui comprend deux fonctions de base pour le chiffrement et le déchiffrement.
Code
Vous pouvez utiliser le code suivant pour implémenter un chiffrement affine -
class Affine(object):
DIE = 128
KEY = (7, 3, 55)
def __init__(self):
pass
def encryptChar(self, char):
K1, K2, kI = self.KEY
return chr((K1 * ord(char) + K2) % self.DIE)
def encrypt(self, string):
return "".join(map(self.encryptChar, string))
def decryptChar(self, char):
K1, K2, KI = self.KEY
return chr(KI * (ord(char) - K2) % self.DIE)
def decrypt(self, string):
return "".join(map(self.decryptChar, string))
affine = Affine()
print affine.encrypt('Affine Cipher')
print affine.decrypt('*18?FMT')
Production
Vous pouvez observer la sortie suivante lorsque vous implémentez un chiffrement affine -
La sortie affiche le message chiffré pour le message en texte brut Affine Cipher et un message déchiffré pour le message envoyé en entrée abcdefg.
Dans ce chapitre, vous découvrirez le chiffrement monoalphabétique et son piratage à l'aide de Python.
Chiffre monoalphabétique
Un chiffrement monoalphabétique utilise une substitution fixe pour chiffrer l'intégralité du message. Un chiffrement monoalphabétique utilisant un dictionnaire Python avec des objets JSON est montré ici -
monoalpha_cipher = {
'a': 'm',
'b': 'n',
'c': 'b',
'd': 'v',
'e': 'c',
'f': 'x',
'g': 'z',
'h': 'a',
'i': 's',
'j': 'd',
'k': 'f',
'l': 'g',
'm': 'h',
'n': 'j',
'o': 'k',
'p': 'l',
'q': 'p',
'r': 'o',
's': 'i',
't': 'u',
'u': 'y',
'v': 't',
'w': 'r',
'x': 'e',
'y': 'w',
'z': 'q',
' ': ' ',
}
Avec l'aide de ce dictionnaire, nous pouvons crypter les lettres avec les lettres associées en tant que valeurs dans l'objet JSON. Le programme suivant crée un programme monoalphabétique en tant que représentation de classe qui comprend toutes les fonctions de cryptage et de décryptage.
from string import letters, digits
from random import shuffle
def random_monoalpha_cipher(pool = None):
if pool is None:
pool = letters + digits
original_pool = list(pool)
shuffled_pool = list(pool)
shuffle(shuffled_pool)
return dict(zip(original_pool, shuffled_pool))
def inverse_monoalpha_cipher(monoalpha_cipher):
inverse_monoalpha = {}
for key, value in monoalpha_cipher.iteritems():
inverse_monoalpha[value] = key
return inverse_monoalpha
def encrypt_with_monoalpha(message, monoalpha_cipher):
encrypted_message = []
for letter in message:
encrypted_message.append(monoalpha_cipher.get(letter, letter))
return ''.join(encrypted_message)
def decrypt_with_monoalpha(encrypted_message, monoalpha_cipher):
return encrypt_with_monoalpha(
encrypted_message,
inverse_monoalpha_cipher(monoalpha_cipher)
)
Ce fichier est appelé plus tard pour implémenter le processus de cryptage et de décryptage du chiffrement Monoalphabetic qui est mentionné ci-dessous -
import monoalphabeticCipher as mc
cipher = mc.random_monoalpha_cipher()
print(cipher)
encrypted = mc.encrypt_with_monoalpha('Hello all you hackers out there!', cipher)
decrypted = mc.decrypt_with_monoalpha('sXGGt SGG Nt0 HSrLXFC t0U UHXFX!', cipher)
print(encrypted)
print(decrypted)
Production
Vous pouvez observer la sortie suivante lorsque vous implémentez le code donné ci-dessus -
Ainsi, vous pouvez pirater un chiffrement monoalphabétique avec une paire clé / valeur spécifiée qui transforme le texte chiffré en texte brut réel.
Le chiffrement de substitution simple est le chiffrement le plus couramment utilisé et comprend un algorithme de substitution de chaque caractère de texte brut pour chaque caractère de texte chiffré. Dans ce processus, les alphabets sont mélangés par rapport à l'algorithme de chiffrement de César.
Exemple
Les clés d'un chiffrement de substitution simple se composent généralement de 26 lettres. Un exemple de clé est -
plain alphabet : abcdefghijklmnopqrstuvwxyz
cipher alphabet: phqgiumeaylnofdxjkrcvstzwb
Un exemple de cryptage utilisant la clé ci-dessus est -
plaintext : defend the east wall of the castle
ciphertext: giuifg cei iprc tpnn du cei qprcni
Le code suivant montre un programme pour implémenter un chiffrement de substitution simple -
import random, sys
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def main():
message = ''
if len(sys.argv) > 1:
with open(sys.argv[1], 'r') as f:
message = f.read()
else:
message = raw_input("Enter your message: ")
mode = raw_input("E for Encrypt, D for Decrypt: ")
key = ''
while checkKey(key) is False:
key = raw_input("Enter 26 ALPHA key (leave blank for random key): ")
if key == '':
key = getRandomKey()
if checkKey(key) is False:
print('There is an error in the key or symbol set.')
translated = translateMessage(message, key, mode)
print('Using key: %s' % (key))
if len(sys.argv) > 1:
fileOut = 'enc.' + sys.argv[1]
with open(fileOut, 'w') as f:
f.write(translated)
print('Success! File written to: %s' % (fileOut))
else: print('Result: ' + translated)
# Store the key into list, sort it, convert back, compare to alphabet.
def checkKey(key):
keyString = ''.join(sorted(list(key)))
return keyString == LETTERS
def translateMessage(message, key, mode):
translated = ''
charsA = LETTERS
charsB = key
# If decrypt mode is detected, swap A and B
if mode == 'D':
charsA, charsB = charsB, charsA
for symbol in message:
if symbol.upper() in charsA:
symIndex = charsA.find(symbol.upper())
if symbol.isupper():
translated += charsB[symIndex].upper()
else:
translated += charsB[symIndex].lower()
else:
translated += symbol
return translated
def getRandomKey():
randomList = list(LETTERS)
random.shuffle(randomList)
return ''.join(randomList)
if __name__ == '__main__':
main()
Production
Vous pouvez observer la sortie suivante lorsque vous implémentez le code donné ci-dessus -
Dans ce chapitre, nous nous concentrerons sur le test du chiffrement de substitution à l'aide de diverses méthodes, ce qui permet de générer des chaînes aléatoires comme indiqué ci-dessous -
import random, string, substitution
def main():
for i in range(1000):
key = substitution.getRandomKey()
message = random_string()
print('Test %s: String: "%s.."' % (i + 1, message[:50]))
print("Key: " + key)
encrypted = substitution.translateMessage(message, key, 'E')
decrypted = substitution.translateMessage(encrypted, key, 'D')
if decrypted != message:
print('ERROR: Decrypted: "%s" Key: %s' % (decrypted, key))
sys.exit()
print('Substutition test passed!')
def random_string(size = 5000, chars = string.ascii_letters + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
if __name__ == '__main__':
main()
Production
Vous pouvez observer la sortie sous forme de chaînes générées au hasard, ce qui aide à générer des messages aléatoires en texte brut, comme indiqué ci-dessous -
Une fois le test terminé avec succès, nous pouvons observer le message de sortie Substitution test passed!.
Ainsi, vous pouvez pirater un chiffrement de substitution de manière systématique.
Dans ce chapitre, vous pouvez en apprendre davantage sur la mise en œuvre simple du chiffrement de substitution qui affiche le message chiffré et déchiffré selon la logique utilisée dans la technique de chiffrement de substitution simple. Cela peut être considéré comme une approche alternative de codage.
Code
Vous pouvez utiliser le code suivant pour effectuer le décryptage en utilisant un chiffrement de substitution simple -
import random
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + \
'abcdefghijklmnopqrstuvwxyz' + \
'0123456789' + \
':.;,?!@#$%&()+=-*/_<> []{}`~^"\'\\'
def generate_key():
"""Generate an key for our cipher"""
shuffled = sorted(chars, key=lambda k: random.random())
return dict(zip(chars, shuffled))
def encrypt(key, plaintext):
"""Encrypt the string and return the ciphertext"""
return ''.join(key[l] for l in plaintext)
def decrypt(key, ciphertext):
"""Decrypt the string and return the plaintext"""
flipped = {v: k for k, v in key.items()}
return ''.join(flipped[l] for l in ciphertext)
def show_result(plaintext):
"""Generate a resulting cipher with elements shown"""
key = generate_key()
encrypted = encrypt(key, plaintext)
decrypted = decrypt(key, encrypted)
print 'Key: %s' % key
print 'Plaintext: %s' % plaintext
print 'Encrypted: %s' % encrypted
print 'Decrypted: %s' % decrypted
show_result('Hello World. This is demo of substitution cipher')
Production
Le code ci-dessus vous donne la sortie comme indiqué ici -
Dans ce chapitre, vous apprendrez en détail les différents modules de cryptographie en Python.
Module de cryptographie
Il comprend toutes les recettes et primitives, et fournit une interface de codage de haut niveau en Python. Vous pouvez installer le module de cryptographie à l'aide de la commande suivante -
pip install cryptography
Code
Vous pouvez utiliser le code suivant pour implémenter le module de cryptographie -
from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher_suite = Fernet(key)
cipher_text = cipher_suite.encrypt("This example is used to demonstrate cryptography module")
plain_text = cipher_suite.decrypt(cipher_text)
Production
Le code donné ci-dessus produit la sortie suivante -
Le code donné ici est utilisé pour vérifier le mot de passe et créer son hachage. Il comprend également une logique de vérification du mot de passe à des fins d'authentification.
import uuid
import hashlib
def hash_password(password):
# uuid is used to generate a random number of the specified password
salt = uuid.uuid4().hex
return hashlib.sha256(salt.encode() + password.encode()).hexdigest() + ':' + salt
def check_password(hashed_password, user_password):
password, salt = hashed_password.split(':')
return password == hashlib.sha256(salt.encode() + user_password.encode()).hexdigest()
new_pass = input('Please enter a password: ')
hashed_password = hash_password(new_pass)
print('The string to store in the db is: ' + hashed_password)
old_pass = input('Now please enter the password again to check: ')
if check_password(hashed_password, old_pass):
print('You entered the right password')
else:
print('Passwords do not match')
Production
Scenario 1 - Si vous avez entré un mot de passe correct, vous pouvez trouver la sortie suivante -
Scenario 2 - Si nous entrons un mot de passe incorrect, vous pouvez trouver la sortie suivante -
Explication
Hashlibpackage est utilisé pour stocker les mots de passe dans une base de données. Dans ce programme,salt est utilisé qui ajoute une séquence aléatoire à la chaîne de mot de passe avant d'implémenter la fonction de hachage.
Vignere Cipher inclut une torsion avec l'algorithme de César Cipher utilisé pour le cryptage et le décryptage. Vignere Cipher fonctionne de manière similaire à l'algorithme de César Cipher avec une seule distinction majeure: César Cipher comprend un algorithme pour le décalage d'un caractère, tandis que Vignere Cipher comprend une clé avec plusieurs alphabets.
Équation mathématique
Pour le cryptage, l'équation mathématique est la suivante -
$$ E_ {k} \ gauche (M {_ {i {}}} \ droite) = \ gauche (M_ {i} + K_ {i} \ droite) \; \; \; mod \; \; 26 $$
Pour le décryptage, l'équation mathématique est la suivante -
$$ D_ {k} \ left (C {_ {i {}}} \ right) = \ left (C_ {i} -K_ {i} \ right) \; \; \; mod \; \; 26 $$
Le chiffrement de Vignere utilise plus d'un ensemble de substitutions, et par conséquent, il est également appelé polyalphabetic cipher. Vignere Cipher utilisera une lettre clé au lieu d'une représentation de clé numérique: la lettre A sera utilisée pour la clé 0, la lettre B pour la clé 1 et ainsi de suite. Les numéros des lettres avant et après le processus de cryptage sont indiqués ci-dessous -
La combinaison possible du nombre de clés possibles en fonction de la longueur de clé Vignere est donnée comme suit, ce qui donne le résultat de la sécurité de l'algorithme de chiffrement Vignere -
Vignere Tableau
Le tableau utilisé pour le chiffrement Vignere est comme indiqué ci-dessous -
Dans ce chapitre, voyons comment implémenter le chiffrement Vignere. Considérez le texteThis is basic implementation of Vignere Cipher doit être encodé et la clé utilisée est PIZZA.
Code
Vous pouvez utiliser le code suivant pour implémenter un chiffrement Vignere en Python -
import pyperclip
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def main():
myMessage = "This is basic implementation of Vignere Cipher"
myKey = 'PIZZA'
myMode = 'encrypt'
if myMode == 'encrypt':
translated = encryptMessage(myKey, myMessage)
elif myMode == 'decrypt':
translated = decryptMessage(myKey, myMessage)
print('%sed message:' % (myMode.title()))
print(translated)
print()
def encryptMessage(key, message):
return translateMessage(key, message, 'encrypt')
def decryptMessage(key, message):
return translateMessage(key, message, 'decrypt')
def translateMessage(key, message, mode):
translated = [] # stores the encrypted/decrypted message string
keyIndex = 0
key = key.upper()
for symbol in message:
num = LETTERS.find(symbol.upper())
if num != -1:
if mode == 'encrypt':
num += LETTERS.find(key[keyIndex])
elif mode == 'decrypt':
num -= LETTERS.find(key[keyIndex])
num %= len(LETTERS)
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())
keyIndex += 1
if keyIndex == len(key):
keyIndex = 0
else:
translated.append(symbol)
return ''.join(translated)
if __name__ == '__main__':
main()
Production
Vous pouvez observer la sortie suivante lorsque vous implémentez le code donné ci-dessus -
Les combinaisons possibles de piratage du chiffrement Vignere sont pratiquement impossibles. Par conséquent, il est considéré comme un mode de cryptage sécurisé.
Le chiffrement par pad à usage unique est un type de chiffrement Vignere qui comprend les fonctionnalités suivantes:
C'est un chiffre incassable.
La clé est exactement la même que la longueur du message qui est chiffré.
La clé est composée de symboles aléatoires.
Comme son nom l'indique, la clé n'est utilisée qu'une seule fois et n'est plus jamais utilisée pour un autre message à chiffrer.
Pour cette raison, le message chiffré sera vulnérable aux attaques d'un cryptanalyste. La clé utilisée pour un chiffrement par pad unique est appeléepad, comme il est imprimé sur des blocs de papier.
Pourquoi est-il incassable?
La clé est incassable grâce aux caractéristiques suivantes -
La clé est aussi longue que le message donné.
La clé est vraiment aléatoire et spécialement générée automatiquement.
Clé et texte brut calculés comme modulo 10/26/2.
Chaque clé doit être utilisée une fois et détruite par l'expéditeur et le destinataire.
Il devrait y avoir deux copies de la clé: une avec l'expéditeur et l'autre avec le destinataire.
Chiffrement
Pour crypter une lettre, un utilisateur doit écrire une clé sous le texte en clair. La lettre en clair est placée en haut et la lettre clé à gauche. La section transversale réalisée entre deux lettres est le texte brut. Il est décrit dans l'exemple ci-dessous -
Décryptage
Pour déchiffrer une lettre, l'utilisateur prend la lettre clé sur la gauche et trouve la lettre de texte chiffrée dans cette ligne. La lettre de texte brut est placée en haut de la colonne où l'utilisateur peut trouver la lettre de texte chiffré.
Python inclut un module d'implémentation hacky pour one-time-padimplémentation de chiffrement. Le nom du package est appelé One-Time-Pad qui comprend un outil de chiffrement de ligne de commande qui utilise un mécanisme de chiffrement similaire à l'algorithme de chiffrement à pad unique.
Installation
Vous pouvez utiliser la commande suivante pour installer ce module -
pip install onetimepad
Si vous souhaitez l'utiliser à partir de la ligne de commande, exécutez la commande suivante -
onetimepad
Code
Le code suivant permet de générer un chiffrement de pad unique -
import onetimepad
cipher = onetimepad.encrypt('One Time Cipher', 'random')
print("Cipher text is ")
print(cipher)
print("Plain text is ")
msg = onetimepad.decrypt(cipher, 'random')
print(msg)
Production
Vous pouvez observer la sortie suivante lorsque vous exécutez le code donné ci-dessus -
Note - Le message chiffré est très facile à déchiffrer si la longueur de la clé est inférieure à la longueur du message (texte brut).
Dans tous les cas, la clé n'est pas nécessairement aléatoire, ce qui fait du chiffrement ponctuel d'un pad un outil utile.
Dans ce chapitre, discutons en détail de la cryptographie symétrique et asymétrique.
Cryptographie symétrique
Dans ce type, le processus de chiffrement et de déchiffrement utilise la même clé. Il est également appelé commesecret key cryptography. Les principales caractéristiques de la cryptographie symétrique sont les suivantes -
- C'est plus simple et plus rapide.
- Les deux parties échangent la clé de manière sécurisée.
Inconvénient
L'inconvénient majeur de la cryptographie symétrique est que si la clé est divulguée à l'intrus, le message peut être facilement modifié et cela est considéré comme un facteur de risque.
Norme de chiffrement des données (DES)
L'algorithme de clé symétrique le plus populaire est Data Encryption Standard (DES) et Python comprend un package qui inclut la logique derrière l'algorithme DES.
Installation
La commande pour l'installation du package DES pyDES en Python est -
pip install pyDES
La mise en œuvre de programme simple de l'algorithme DES est la suivante -
import pyDes
data = "DES Algorithm Implementation"
k = pyDes.des("DESCRYPT", pyDes.CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5)
d = k.encrypt(data)
print "Encrypted: %r" % d
print "Decrypted: %r" % k.decrypt(d)
assert k.decrypt(d) == data
Il appelle la variable padmode qui récupère tous les packages selon la mise en œuvre de l'algorithme DES et suit le cryptage et le décryptage d'une manière spécifiée.
Production
Vous pouvez voir la sortie suivante à la suite du code donné ci-dessus -
Cryptographie asymétrique
Il est également appelé comme public key cryptography.Cela fonctionne à l'inverse de la cryptographie symétrique. Cela implique qu'il nécessite deux clés: une pour le cryptage et l'autre pour le décryptage. La clé publique est utilisée pour le chiffrement et la clé privée est utilisée pour le déchiffrement.
Inconvénient
- En raison de sa longueur de clé, il contribue à une vitesse de cryptage inférieure.
- La gestion des clés est cruciale.
Le code de programme suivant en Python illustre le fonctionnement de la cryptographie asymétrique utilisant l'algorithme RSA et son implémentation -
from Crypto import Random
from Crypto.PublicKey import RSA
import base64
def generate_keys():
# key length must be a multiple of 256 and >= 1024
modulus_length = 256*4
privatekey = RSA.generate(modulus_length, Random.new().read)
publickey = privatekey.publickey()
return privatekey, publickey
def encrypt_message(a_message , publickey):
encrypted_msg = publickey.encrypt(a_message, 32)[0]
encoded_encrypted_msg = base64.b64encode(encrypted_msg)
return encoded_encrypted_msg
def decrypt_message(encoded_encrypted_msg, privatekey):
decoded_encrypted_msg = base64.b64decode(encoded_encrypted_msg)
decoded_decrypted_msg = privatekey.decrypt(decoded_encrypted_msg)
return decoded_decrypted_msg
a_message = "This is the illustration of RSA algorithm of asymmetric cryptography"
privatekey , publickey = generate_keys()
encrypted_msg = encrypt_message(a_message , publickey)
decrypted_msg = decrypt_message(encrypted_msg, privatekey)
print "%s - (%d)" % (privatekey.exportKey() , len(privatekey.exportKey()))
print "%s - (%d)" % (publickey.exportKey() , len(publickey.exportKey()))
print " Original content: %s - (%d)" % (a_message, len(a_message))
print "Encrypted message: %s - (%d)" % (encrypted_msg, len(encrypted_msg))
print "Decrypted message: %s - (%d)" % (decrypted_msg, len(decrypted_msg))
Production
Vous pouvez trouver la sortie suivante lorsque vous exécutez le code donné ci-dessus -
L'algorithme RSA est une technique de cryptage à clé publique et est considéré comme le moyen de cryptage le plus sûr. Il a été inventé par Rivest, Shamir et Adleman en 1978 et d'où son nomRSA algorithme.
Algorithme
L'algorithme RSA possède les fonctionnalités suivantes -
L'algorithme RSA est une exponentiation populaire dans un champ fini sur des entiers comprenant des nombres premiers.
Les nombres entiers utilisés par cette méthode sont suffisamment grands, ce qui rend sa résolution difficile.
Il existe deux ensembles de clés dans cet algorithme: la clé privée et la clé publique.
Vous devrez suivre les étapes suivantes pour travailler sur l'algorithme RSA -
Étape 1: Générer le module RSA
La procédure initiale commence par la sélection de deux nombres premiers à savoir p et q, puis le calcul de leur produit N, comme indiqué -
N=p*q
Ici, soit N le grand nombre spécifié.
Étape 2: Nombre dérivé (e)
Considérez le nombre e comme un nombre dérivé qui devrait être supérieur à 1 et inférieur à (p-1) et (q-1). La condition principale sera qu'il ne doit y avoir aucun facteur commun de (p-1) et (q-1) sauf 1
Étape 3: clé publique
La paire de nombres spécifiée n et e forme la clé publique RSA et elle est rendue publique.
Étape 4: Clé privée
Clé privée dest calculé à partir des nombres p, q et e. La relation mathématique entre les nombres est la suivante -
ed = 1 mod (p-1) (q-1)
La formule ci-dessus est la formule de base de l'algorithme euclidien étendu, qui prend p et q comme paramètres d'entrée.
Formule de cryptage
Prenons l'exemple d'un expéditeur qui envoie le message en texte brut à quelqu'un dont la clé publique est (n,e). Pour crypter le message en texte brut dans le scénario donné, utilisez la syntaxe suivante -
C = Pe mod n
Formule de décryptage
Le processus de décryptage est très simple et inclut des analyses pour le calcul dans une approche systématique. Considérant le récepteur C a la clé privée d, le module de résultat sera calculé comme -
Plaintext = Cd mod n
Dans ce chapitre, nous nous concentrerons sur l'implémentation par étapes de l'algorithme RSA en utilisant Python.
Générer des clés RSA
Les étapes suivantes sont impliquées dans la génération des clés RSA -
Créez deux grands nombres premiers à savoir p et q. Le produit de ces nombres sera appelén, où n= p*q
Générer un nombre aléatoire relativement premier avec (p-1) et (q-1). Que le numéro soit appelé comme e.
Calculez l'inverse modulaire de e. L'inverse calculé sera appelé commed.
Algorithmes de génération de clés RSA
Nous avons besoin de deux algorithmes principaux pour générer des clés RSA à l'aide de Python - Cryptomath module et Rabin Miller module.
Module Cryptomath
Le code source du module cryptomath qui suit toute l'implémentation de base de l'algorithme RSA est le suivant -
def gcd(a, b):
while a != 0:
a, b = b % a, a
return b
def findModInverse(a, m):
if gcd(a, m) != 1:
return None
u1, u2, u3 = 1, 0, a
v1, v2, v3 = 0, 1, m
while v3 != 0:
q = u3 // v3
v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
return u1 % m
Module RabinMiller
Le code source du module RabinMiller qui suit toute l'implémentation de base de l'algorithme RSA est le suivant -
import random
def rabinMiller(num):
s = num - 1
t = 0
while s % 2 == 0:
s = s // 2
t += 1
for trials in range(5):
a = random.randrange(2, num - 1)
v = pow(a, s, num)
if v != 1:
i = 0
while v != (num - 1):
if i == t - 1:
return False
else:
i = i + 1
v = (v ** 2) % num
return True
def isPrime(num):
if (num 7< 2):
return False
lowPrimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241,
251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449,
457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787,
797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907,
911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
if num in lowPrimes:
return True
for prime in lowPrimes:
if (num % prime == 0):
return False
return rabinMiller(num)
def generateLargePrime(keysize = 1024):
while True:
num = random.randrange(2**(keysize-1), 2**(keysize))
if isPrime(num):
return num
Le code complet pour générer des clés RSA est le suivant -
import random, sys, os, rabinMiller, cryptomath
def main():
makeKeyFiles('RSA_demo', 1024)
def generateKey(keySize):
# Step 1: Create two prime numbers, p and q. Calculate n = p * q.
print('Generating p prime...')
p = rabinMiller.generateLargePrime(keySize)
print('Generating q prime...')
q = rabinMiller.generateLargePrime(keySize)
n = p * q
# Step 2: Create a number e that is relatively prime to (p-1)*(q-1).
print('Generating e that is relatively prime to (p-1)*(q-1)...')
while True:
e = random.randrange(2 ** (keySize - 1), 2 ** (keySize))
if cryptomath.gcd(e, (p - 1) * (q - 1)) == 1:
break
# Step 3: Calculate d, the mod inverse of e.
print('Calculating d that is mod inverse of e...')
d = cryptomath.findModInverse(e, (p - 1) * (q - 1))
publicKey = (n, e)
privateKey = (n, d)
print('Public key:', publicKey)
print('Private key:', privateKey)
return (publicKey, privateKey)
def makeKeyFiles(name, keySize):
# Creates two files 'x_pubkey.txt' and 'x_privkey.txt'
(where x is the value in name) with the the n,e and d,e integers written in them,
# delimited by a comma.
if os.path.exists('%s_pubkey.txt' % (name)) or os.path.exists('%s_privkey.txt' % (name)):
sys.exit('WARNING: The file %s_pubkey.txt or %s_privkey.txt already exists! Use a different name or delete these files and re-run this program.' % (name, name))
publicKey, privateKey = generateKey(keySize)
print()
print('The public key is a %s and a %s digit number.' % (len(str(publicKey[0])), len(str(publicKey[1]))))
print('Writing public key to file %s_pubkey.txt...' % (name))
fo = open('%s_pubkey.txt' % (name), 'w')
fo.write('%s,%s,%s' % (keySize, publicKey[0], publicKey[1]))
fo.close()
print()
print('The private key is a %s and a %s digit number.' % (len(str(publicKey[0])), len(str(publicKey[1]))))
print('Writing private key to file %s_privkey.txt...' % (name))
fo = open('%s_privkey.txt' % (name), 'w')
fo.write('%s,%s,%s' % (keySize, privateKey[0], privateKey[1]))
fo.close()
# If makeRsaKeys.py is run (instead of imported as a module) call
# the main() function.
if __name__ == '__main__':
main()
Production
La clé publique et les clés privées sont générées et enregistrées dans les fichiers respectifs comme indiqué dans la sortie suivante.
Dans ce chapitre, nous nous concentrerons sur différentes implémentations du chiffrement RSA et les fonctions impliquées pour celui-ci. Vous pouvez faire référence ou inclure ce fichier python pour implémenter l'implémentation de l'algorithme de chiffrement RSA.
Les modules inclus pour l'algorithme de chiffrement sont les suivants -
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode
hash = "SHA-256"
Nous avons initialisé la valeur de hachage en SHA-256 pour une meilleure sécurité. Nous utiliserons une fonction pour générer de nouvelles clés ou une paire de clés publique et privée en utilisant le code suivant.
def newkeys(keysize):
random_generator = Random.new().read
key = RSA.generate(keysize, random_generator)
private, public = key, key.publickey()
return public, private
def importKey(externKey):
return RSA.importKey(externKey)
Pour le cryptage, la fonction suivante est utilisée qui suit l'algorithme RSA -
def encrypt(message, pub_key):
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)
Deux paramètres sont obligatoires: message et pub_keyqui fait référence à la clé publique. Une clé publique est utilisée pour le chiffrement et une clé privée est utilisée pour le déchiffrement.
Le programme complet pour la procédure de cryptage est mentionné ci-dessous -
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode
hash = "SHA-256"
def newkeys(keysize):
random_generator = Random.new().read
key = RSA.generate(keysize, random_generator)
private, public = key, key.publickey()
return public, private
def importKey(externKey):
return RSA.importKey(externKey)
def getpublickey(priv_key):
return priv_key.publickey()
def encrypt(message, pub_key):
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)
Ce chapitre est une continuation du chapitre précédent où nous avons suivi la mise en œuvre étape par étape du chiffrement à l'aide de l'algorithme RSA et en discute en détail.
La fonction utilisée pour déchiffrer le texte chiffré est la suivante -
def decrypt(ciphertext, priv_key):
cipher = PKCS1_OAEP.new(priv_key)
return cipher.decrypt(ciphertext)
Pour la cryptographie à clé publique ou la cryptographie à clé asymétrique, il est important de conserver deux caractéristiques importantes à savoir Authentication et Authorization.
Autorisation
L'autorisation est le processus permettant de confirmer que l'expéditeur est le seul à avoir transmis le message. Le code suivant explique cela -
def sign(message, priv_key, hashAlg="SHA-256"):
global hash
hash = hashAlg
signer = PKCS1_v1_5.new(priv_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.sign(digest)
Authentification
L'authentification est possible par la méthode de vérification qui est expliquée ci-dessous -
def verify(message, signature, pub_key):
signer = PKCS1_v1_5.new(pub_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.verify(digest, signature)
La signature numérique est vérifiée avec les détails de l'expéditeur et du destinataire. Cela ajoute plus d'âge pour des raisons de sécurité.
Décryptage du chiffrement RSA
Vous pouvez utiliser le code suivant pour le décryptage du chiffrement RSA -
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode
hash = "SHA-256"
def newkeys(keysize):
random_generator = Random.new().read
key = RSA.generate(keysize, random_generator)
private, public = key, key.publickey()
return public, private
def importKey(externKey):
return RSA.importKey(externKey)
def getpublickey(priv_key):
return priv_key.publickey()
def encrypt(message, pub_key):
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)
def decrypt(ciphertext, priv_key):
cipher = PKCS1_OAEP.new(priv_key)
return cipher.decrypt(ciphertext)
def sign(message, priv_key, hashAlg = "SHA-256"):
global hash
hash = hashAlg
signer = PKCS1_v1_5.new(priv_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.sign(digest)
def verify(message, signature, pub_key):
signer = PKCS1_v1_5.new(pub_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.verify(digest, signature)
Le piratage du chiffrement RSA est possible avec de petits nombres premiers, mais il est considéré comme impossible s'il est utilisé avec de grands nombres. Les raisons qui spécifient pourquoi il est difficile de pirater le chiffrement RSA sont les suivantes -
L'attaque par force brute ne fonctionnerait pas car il y a trop de clés possibles pour travailler. En outre, cela prend beaucoup de temps.
L'attaque par dictionnaire ne fonctionnera pas dans l'algorithme RSA car les clés sont numériques et n'incluent aucun caractère.
L'analyse de fréquence des caractères est très difficile à suivre car un seul bloc crypté représente différents caractères.
Il n'y a pas d'astuces mathématiques spécifiques pour pirater le chiffrement RSA.
L'équation de décryptage RSA est -
M = C^d mod n
À l'aide de petits nombres premiers, nous pouvons essayer de pirater le chiffrement RSA et l'exemple de code pour le même est mentionné ci-dessous -
def p_and_q(n):
data = []
for i in range(2, n):
if n % i == 0:
data.append(i)
return tuple(data)
def euler(p, q):
return (p - 1) * (q - 1)
def private_index(e, euler_v):
for i in range(2, euler_v):
if i * e % euler_v == 1:
return i
def decipher(d, n, c):
return c ** d % n
def main():
e = int(input("input e: "))
n = int(input("input n: "))
c = int(input("input c: "))
# t = 123
# private key = (103, 143)
p_and_q_v = p_and_q(n)
# print("[p_and_q]: ", p_and_q_v)
euler_v = euler(p_and_q_v[0], p_and_q_v[1])
# print("[euler]: ", euler_v)
d = private_index(e, euler_v)
plain = decipher(d, n, c)
print("plain: ", plain)
if __name__ == "__main__":
main()
Production
Le code ci-dessus produit la sortie suivante -