Python密码学快速指南
Python密码学 - 概述
密码学是通过编码消息在两个用户之间进行通信的艺术。密码学的科学起源于为从一方到另一方传输的机密消息提供安全性的基本动机。
密码学被定义为隐藏消息以引入隐私和保密性的艺术和科学,正如信息安全中所认识的那样。
密码学术语
这里解释了密码学中常用的术语:
明文
明文消息是可以阅读并且所有用户都能理解的文本。明文是经过密码学处理的消息。
密文
密文是在明文上应用密码学后获得的消息。
加密
将明文转换为密文的过程称为加密。它也称为编码。
解密
将密文转换为明文的过程称为解密。它也称为解码。
下图显示了完整密码学过程的示意图:
现代密码学的特点
现代密码学的基本特征如下:
它处理位序列。
它使用数学算法来保护信息。
它需要对安全通信通道感兴趣的各方来实现隐私。
双重强度加密
双重强度加密,也称为多重加密,是将已经加密的文本加密一次或多次的过程,可以使用相同的或不同的算法/模式。
双重强度加密的其他名称包括级联加密或级联密码。
双重强度加密的级别
双重强度加密包括以下解释的各个加密级别:
第一层加密
使用哈希算法和对称密钥从原始可读消息生成密文。之后,使用非对称密钥加密对称密钥。此模式的最佳说明是将密文的哈希摘要合并到一个封装中。接收者将首先计算摘要,然后解密文本以验证文本在传输过程中是否未被篡改。
第二层加密
第二层加密是使用相同或不同的算法向密文添加另一层加密的过程。通常,为此使用 32 位字符长的对称密码。
第三层加密
在此过程中,加密的封装通过 SSL/TLS 连接传输到通信伙伴。
下图以图示方式显示了双重加密过程:
混合密码学
混合密码学是将多种不同类型的密码组合在一起的过程,它结合了每种密码的优点。通常遵循一种常见的方法,即为对称密码生成一个随机密钥,然后通过非对称密钥密码加密此密钥。
由于这种模式,原始消息本身使用对称密码加密,然后使用密钥。接收者在收到消息后,首先使用自己的私钥解密消息,然后使用指定的密钥解密消息。
Python概述及安装
Python是一种开源脚本语言,它是高级的、解释型的、交互式的和面向对象的。它的设计易于阅读。Python语言的语法易于理解,并经常使用英语关键字。
Python语言的特性
Python提供了以下主要特性:
解释型
Python在运行时使用解释器进行处理。无需在执行前编译程序。它类似于PERL和PHP。
面向对象
Python遵循面向对象的样式和设计模式。它包括类定义,具有封装和多态性等各种特性。
Python语言的关键点
Python编程语言的关键点如下:
它包括函数式和结构化编程和方法以及面向对象编程方法。
它可以用作脚本语言或编程语言。
它包括自动垃圾回收。
它包含高级动态数据类型,并支持各种动态类型检查。
Python具有与C、C++和Java等语言集成的特性。
Python语言的下载链接如下:www.python.org/downloads它包括适用于Windows、MacOS和Linux发行版等各种操作系统的软件包。
Python字符串
字符串的基本声明如下所示:
str = 'Hello World!'
Python列表
Python的列表可以声明为复合数据类型,用逗号分隔,并用方括号([])括起来。
list = [ 'abcd', 786 , 2.23, 'john', 70.2 ] tinylist = [123, 'john']
Python元组
元组是Python的一种动态数据类型,它由多个用逗号分隔的值组成。元组用括号括起来。
tinytuple = (123, 'john')
Python字典
Python字典是一种哈希表。字典键几乎可以是Python的任何数据类型,通常是数字或字符串。
tinydict = {'name': 'omkar','code':6734, 'dept': 'sales'}
密码学包
Python包含一个名为cryptography的包,它提供密码学配方和原语。它支持Python 2.7、Python 3.4+和PyPy 5.3+。cryptography包的基本安装是通过以下命令实现的:
pip install cryptography
有各种包,既有高级配方,也有对常见密码算法(如对称密码、消息摘要和密钥派生函数)的低级接口。
在本教程中,我们将使用Python的各种包来实现密码算法。
Python密码学 - 反向密码
上一章介绍了如何在本地计算机上安装Python。本章将详细介绍反向密码及其编码。
反向密码算法
反向密码算法具有以下特性:
反向密码使用反转明文字符串的模式将其转换为密文。
加密和解密过程相同。
要解密密文,用户只需反转密文即可获得明文。
缺点
反向密码的主要缺点是它非常弱。黑客可以轻松地破解密文以获取原始消息。因此,反向密码不被认为是维护安全通信通道的好选择。
示例
考虑一个示例,其中语句This is program to explain reverse cipher 将使用反向密码算法来实现。以下Python代码使用该算法来获得输出。
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)
输出
您可以看到反转后的文本,即如下图所示的输出:
解释
明文存储在变量message中,translated变量用于存储创建的密文。
使用for循环和索引号计算明文的长度。字符存储在密文变量translated中,并在最后一行打印。
Python密码学 - 凯撒密码
在上一章中,我们讨论了反向密码。本章详细介绍凯撒密码。
凯撒密码算法
凯撒密码算法具有以下特性:
凯撒密码技术是一种简单易用的加密技术。
它是一种简单的替换密码。
明文的每个字母都替换为字母表中固定数量位置下的字母。
下图描绘了凯撒密码算法实现的工作原理:
凯撒密码算法的程序实现如下:
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)
输出
您可以看到凯撒密码,即如下图所示的输出:
解释
明文字符逐个遍历。
对于给定明文中的每个字符,根据文本加密和解密的过程,根据规则转换给定的字符。
步骤完成后,会生成一个新的字符串,称为密文。
凯撒密码算法的破解
密文可以通过各种可能性进行破解。其中一种可能性是暴力破解技术,它涉及尝试所有可能的解密密钥。这种技术不需要太多努力,对于黑客来说相对简单。
破解凯撒密码算法的程序实现如下:
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))
考虑上例中加密的密文。然后,使用密钥和暴力破解攻击技术的可能破解方法的输出如下:
Python密码学 - ROT13算法
到目前为止,您已经学习了反向密码和凯撒密码算法。现在,让我们讨论ROT13算法及其实现。
ROT13算法解释
ROT13密码指的是旋转13位的缩写形式。它是凯撒密码的一个特例,其中移位始终为13。每个字母都移位13位来加密或解密消息。
示例
下图以图示方式解释了ROT13算法过程:
程序代码
ROT13算法的程序实现如下:
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()
您可以看到如下所示的ROT13输出:
缺点
ROT13算法使用13次移位。因此,反向移位字符来解密密文非常容易。
ROT13算法分析
ROT13密码算法被认为是凯撒密码的一种特例。它不是一个非常安全的算法,很容易通过频率分析或尝试所有25个可能的密钥来破解,而ROT13可以通过移位13位来破解。因此,它没有任何实际用途。
转置密码
转置密码是一种密码算法,其中明文中的字母顺序被重新排列以形成密文。在这个过程中,不会包含实际的明文字母。
示例
列置换密码是一个简单的转置密码示例,其中明文中的每个字符都以指定的字母宽度水平写入。密文垂直写入,从而创建一个完全不同的密文。
考虑明文hello world,让我们应用如下所示的简单列置换技术
明文字符水平放置,密文以垂直格式创建为holewdlo lr。现在,接收者必须使用相同的表格将密文解密回明文。
代码
下面的程序代码演示了列置换技术的基本实现:
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'))
解释
使用函数split_len(),我们可以分割明文字符,这些字符可以放置在列格式或行格式中。
encode方法有助于使用指定列数的密钥创建密文,并通过读取每一列的字符来打印密文。
输出
列置换技术基本实现的程序代码给出以下输出:
注意- 密码分析员观察到,当执行转置技术时,密码安全性有了显著提高。他们还注意到,使用相同的转置密码重新加密密文可以提高安全性。
转置密码加密
在上一章中,我们学习了转置密码。在本章中,让我们讨论它的加密。
Pyperclip
Python编程语言中pyperclip插件的主要用途是执行跨平台模块,用于复制和粘贴文本到剪贴板。您可以使用如下所示的命令安装python pyperclip模块
pip install pyperclip
如果系统中已存在该需求,您可以看到以下输出:
代码
下面显示了加密转置密码的python代码,其中pyperclip是主模块:
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()
输出
使用pyperclip作为主模块的加密转置密码的程序代码给出以下输出:
解释
函数main()调用encryptMessage(),其中包括使用len函数分割字符并以列格式迭代它们的程序。
主函数在最后初始化以获得适当的输出。
转置密码解密
在本章中,您将学习解密转置密码的步骤。
代码
观察以下代码,以便更好地理解如何解密转置密码。消息Transposition Cipher的密文,密钥为6,获取为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()
解释
密文和提到的密钥是作为解码或解密密文的两个输入参数,通过将字符放置在列格式中并以水平方式读取它们,以反向技术进行解密。
您可以使用以下代码片段将字母放置在列格式中,然后将它们组合或连接在一起:
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)
输出
解密转置密码的程序代码给出以下输出:
文件加密
在Python中,可以在传输到通信信道之前加密和解密文件。为此,您必须使用插件PyCrypto。您可以使用以下命令安装此插件。
pip install pycrypto
代码
下面提到了使用密码保护加密文件的程序代码:
# =================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()
您可以使用以下命令执行加密过程以及密码:
python pyfilecipher-encrypt.py -i file_path_for_encryption -o output_path -p password
输出
执行上面给出的代码时,您可以观察到以下输出:
解释
密码使用MD5哈希算法生成,值存储在Windows系统中的简单安全备份文件中,其中包括如下显示的值:
文件解密
在本章中,让我们讨论使用Python进行密码学文件解密。请注意,对于解密过程,我们将遵循相同的步骤,但不是指定输出路径,我们将关注输入路径或必要的加密文件。
代码
以下是使用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()
您可以使用以下命令执行上述代码:
python pyfilecipher-decrypt.py -i encrypted_file_path -p password
输出
执行上述命令时,您可以观察到以下代码:
注意- 输出指定了加密前和解密后的哈希值,这表明加密了相同的文件,并且该过程成功。
Base64编码和解码
Base64编码将二进制数据转换为文本格式,该文本格式通过通信信道传递,用户可以在其中安全地处理文本。Base64也称为隐私增强电子邮箱(PEM),主要用于电子邮件加密过程。
Python包含一个名为BASE64的模块,其中包含两个主要函数,如下所示:
base64.decode(input, output)- 它解码指定的输入值参数,并将解码后的输出存储为对象。
Base64.encode(input, output)- 它编码指定的输入值参数,并将解码后的输出存储为对象。
编码程序
您可以使用以下代码片段执行base64编码:
import base64 encoded_data = base64.b64encode("Encode this text") print("Encoded text with base 64 is") print(encoded_data)
输出
base64编码的代码将为您提供以下输出:
解码程序
您可以使用以下代码片段执行base64解码:
import base64 decoded_data = base64.b64decode("RW5jb2RlIHRoaXMgdGV4dA==") print("decoded text is ") print(decoded_data)
输出
base64解码的代码将为您提供以下输出:
ASCII和base64的区别
当您使用ASCII和base64进行数据编码时,您可以观察到以下区别:
当您使用ASCII编码文本时,您从文本字符串开始,并将其转换为字节序列。
当您使用Base64编码数据时,您从字节序列开始,并将其转换为文本字符串。
缺点
Base64算法通常用于在数据库中存储密码。主要缺点是每个解码的单词都可以通过任何在线工具轻松编码,入侵者可以轻松获取信息。
Python密码学 - XOR过程
在本章中,让我们了解XOR过程及其在Python中的编码。
算法
加密和解密的XOR算法将明文转换为ASCII字节格式,并使用XOR过程将其转换为指定的字节。它为用户提供了以下优势:
- 快速计算
- 左右两侧没有区别
- 易于理解和分析
代码
您可以使用以下代码片段执行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)
输出
XOR过程的代码将为您提供以下输出:
解释
函数xor_crypt_string()包含一个参数,用于指定编码和解码模式以及字符串值。
基本函数使用base64模块,该模块遵循XOR过程/运算来加密或解密明文/密文。
注意- XOR加密用于加密数据,并且难以通过暴力破解方法破解,即通过生成随机加密密钥以匹配正确的密文。
乘法密码
使用凯撒密码技术时,加密和解密符号涉及使用简单的加法或减法过程将值转换为数字。
如果使用乘法转换为密文,则称为“环绕”情况。考虑如下所示的字母和关联的数字:
数字将用于乘法过程,关联密钥为7。在这种情况下用于生成乘法密码的基本公式如下:
(Alphabet Number * key)mod(total number of alphabets)
通过输出获取的数字映射到上面提到的表中,相应的字母作为加密字母。
Python中乘法密码的基本调制函数如下:
def unshift(key, ch): offset = ord(ch) - ASC_A return chr(((key[0] * (offset + key[1])) % WIDTH) + ASC_A)
注意- 乘法密码的优点是它可以使用非常大的密钥,例如8,953,851。计算机需要很长时间才能暴力破解大部分九百万个密钥。
Python密码学 - 仿射密码
仿射密码是乘法密码和凯撒密码算法的组合。仿射密码的基本实现如下图所示:
在本章中,我们将通过创建包含加密和解密两个基本函数的相应类来实现仿射密码。
代码
您可以使用以下代码实现仿射密码:
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')
输出
实现仿射密码时,您可以观察到以下输出:
输出显示明文消息Affine Cipher的加密消息和作为输入发送的消息abcdefg的解密消息。
破解单字母替换密码
在本章中,您将学习单表密码及其使用Python的破解方法。
单表密码
单表密码使用固定的替换来加密整个消息。这里显示了一个使用带有JSON对象的Python字典的单表密码:
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', ' ': ' ', }
借助此字典,我们可以使用JSON对象中作为值的关联字母来加密字母。以下程序创建一个单表程序作为类表示,其中包含加密和解密的所有函数。
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) )
稍后调用此文件以实现下面提到的单表密码的加密和解密过程:
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)
输出
实现上述代码后,您可以观察到以下输出:
因此,您可以破解具有指定键值对的单字母替换密码,并将密文破解为实际明文。
简单替换密码
简单替换密码是最常用的密码,它包含一个算法,用于将每个明文字符替换为每个密文字符。在这个过程中,与凯撒密码算法相比,字母是混乱的。
示例
简单替换密码的密钥通常由26个字母组成。一个示例密钥是:
plain alphabet : abcdefghijklmnopqrstuvwxyz cipher alphabet: phqgiumeaylnofdxjkrcvstzwb
使用上述密钥的示例加密是:
plaintext : defend the east wall of the castle ciphertext: giuifg cei iprc tpnn du cei qprcni
以下代码显示了一个实现简单替换密码的程序:
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()
输出
实现上述代码后,您可以观察到以下输出:
简单替换密码测试
在本章中,我们将重点介绍使用各种方法测试替换密码,这有助于生成如下所示的随机字符串:
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()
输出
您可以观察到输出为随机生成的字符串,这有助于生成随机明文消息,如下所示:
测试成功完成后,我们可以观察到输出消息替换测试通过!
因此,您可以以系统的方式破解替换密码。
简单替换密码解密
在本章中,您可以学习简单替换密码的简单实现,该实现根据简单替换密码技术中使用的逻辑显示加密和解密消息。这可以被认为是一种替代的编码方法。
代码
您可以使用以下代码使用简单替换密码执行解密:
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')
输出
上述代码给出的输出如下所示:
Python密码学模块
在本章中,您将详细了解Python中密码学的各个模块。
密码学模块
它包含所有配方和原语,并提供Python编码的高级接口。您可以使用以下命令安装密码学模块:
pip install cryptography
代码
您可以使用以下代码实现密码学模块:
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)
输出
上面给出的代码产生以下输出:
此处给出的代码用于验证密码并创建其哈希值。它还包括用于验证密码以进行身份验证的逻辑。
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')
输出
场景1 - 如果您输入了正确的密码,您可以找到以下输出:
场景2 - 如果我们输入错误的密码,您可以找到以下输出:
解释
Hashlib包用于将密码存储在数据库中。在这个程序中,使用salt在实现哈希函数之前向密码字符串添加随机序列。
了解维吉尼亚密码
维吉尼亚密码包含凯撒密码算法用于加密和解密的改进。维吉尼亚密码的工作方式类似于凯撒密码算法,只有一个主要区别:凯撒密码包含单字符移位的算法,而维吉尼亚密码包含多字母移位的密钥。
数学公式
对于加密,数学公式如下:
$$E_{k}\left ( M{_{i{}}} \right ) = \left ( M_{i}+K_{i} \right )\;\;\; mod \;\; 26$$
对于解密,数学公式如下:
$$D_{k}\left ( C{_{i{}}} \right ) = \left ( C_{i}-K_{i} \right )\;\;\; mod \;\; 26$$
维吉尼亚密码使用多个替换集,因此它也称为多字母替换密码。维吉尼亚密码将使用字母密钥而不是数字密钥表示:字母A将用于密钥0,字母B用于密钥1,依此类推。加密过程前后字母的数字如下所示:
基于维吉尼亚密钥长度的可能密钥数量组合如下所示,这说明了维吉尼亚密码算法的安全性:
维吉尼亚方阵
维吉尼亚密码使用的方阵如下所示:
实现维吉尼亚密码
在本章中,让我们了解如何实现维吉尼亚密码。假设文本This is basic implementation of Vignere Cipher需要编码,使用的密钥是PIZZA。
代码
您可以使用以下代码在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()
输出
实现上述代码后,您可以观察到以下输出:
破解维吉尼亚密码的可能性几乎是不可能的。因此,它被认为是一种安全的加密模式。
一次性密码本密码
一次性密码本密码是一种维吉尼亚密码,具有以下特点:
它是一种不可破译的密码。
密钥与加密消息的长度完全相同。
密钥由随机符号组成。
顾名思义,密钥只使用一次,并且永远不会再次用于任何其他需要加密的消息。
因此,加密消息将容易受到密码分析师的攻击。一次性密码本密码中使用的密钥称为密码本,因为它印在纸张上。
为什么它不可破译?
由于以下特点,密钥不可破译:
密钥与给定消息一样长。
密钥是真正的随机数,并且是专门自动生成的。
密钥和明文计算为模10/26/2。
每个密钥都应使用一次并由发送方和接收方销毁。
密钥应有两份副本:发送方一份,接收方一份。
加密
要加密一个字母,用户需要在其下方的明文下写一个密钥。明文字母放在顶部,密钥字母放在左侧。两个字母之间产生的交叉部分就是明文。这在下面的示例中进行了描述:
解密
要解密一个字母,用户在左侧取密钥字母,并在该行中找到密文字母。明文字母位于用户可以找到密文字母的列的顶部。
一次性密码本密码的实现
Python包含一个用于一次性密码本密码实现的hacky实现模块。包名称称为One-Time-Pad,它包含一个命令行加密工具,该工具使用类似于一次性密码本密码算法的加密机制。
安装
您可以使用以下命令安装此模块:
pip install onetimepad
如果您希望从命令行使用它,请运行以下命令:
onetimepad
代码
以下代码有助于生成一次性密码本密码:
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)
输出
运行上述代码时,您可以观察到以下输出:
注意 - 如果密钥的长度小于消息(明文)的长度,则加密消息很容易被破解。
无论如何,密钥不一定是随机的,这使得一次性密码本密码成为一个有价值的工具。
对称和非对称密码学
在本章中,让我们详细讨论对称和非对称密码学。
对称密码学
在这种类型中,加密和解密过程使用相同的密钥。它也称为秘密密钥密码学。对称密码学的主要特点如下:
- 它更简单、更快。
- 双方以安全的方式交换密钥。
缺点
对称密码学的主要缺点是,如果密钥泄露给入侵者,则消息很容易被更改,这被认为是一个风险因素。
数据加密标准 (DES)
最流行的对称密钥算法是数据加密标准 (DES),Python 包含一个包含DES算法背后逻辑的包。
安装
在Python中安装DES包pyDES的命令是:
pip install pyDES
DES算法的简单程序实现如下:
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
它调用变量padmode,该变量根据DES算法实现获取所有包,并以指定的方式执行加密和解密。
输出
您可以看到以下输出作为上述代码的结果:
非对称密码学
它也称为公钥密码学。它的工作方式与对称密码学相反。这意味着它需要两个密钥:一个用于加密,另一个用于解密。公钥用于加密,私钥用于解密。
缺点
- 由于其密钥长度,它导致加密速度降低。
- 密钥管理至关重要。
Python中的以下程序代码说明了使用RSA算法及其实现的非对称密码学的工作原理:
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))
输出
执行上述代码时,您可以找到以下输出:
理解RSA算法
RSA算法是一种公钥加密技术,被认为是最安全的加密方式。它是由Rivest、Shamir和Adleman于1978年发明的,因此命名为RSA算法。
算法
RSA算法具有以下特点:
RSA算法是在包括素数在内的整数上的有限域中的流行求幂。
此方法使用的整数足够大,难以求解。
此算法中有两组密钥:私钥和公钥。
您必须按照以下步骤操作才能使用RSA算法:
步骤1:生成RSA模数
初始过程从选择两个素数p和q开始,然后计算它们的乘积N,如下所示:
N=p*q
这里,设N为指定的大的数。
步骤2:导出数(e)
将数e视为一个导出数,它应该大于1且小于(p-1)和(q-1)。主要条件是(p-1)和(q-1)除了1之外不应该有共同的因子。
步骤3:公钥
指定的数字对n和e构成RSA公钥,它是公开的。
步骤4:私钥
私钥d由数字p、q和e计算得出。数字之间的数学关系如下:
ed = 1 mod (p-1) (q-1)
上述公式是扩展欧几里得算法的基本公式,它以p和q作为输入参数。
加密公式
假设发送方将明文消息发送给公钥为(n,e)的人。要在给定情况下加密明文消息,请使用以下语法:
C = Pe mod n
解密公式
解密过程非常简单,包括以系统的方式进行计算的分析。假设接收方C拥有私钥d,则结果模将计算为:
Plaintext = Cd mod n
创建RSA密钥
在本章中,我们将重点介绍使用Python逐步实现RSA算法。
生成RSA密钥
生成RSA密钥涉及以下步骤:
创建两个大的素数,即p和q。这两个数的乘积称为n,其中n= p*q
生成一个与(p-1)和(q-1)互素的随机数。将该数称为e。
计算e的模反元素。计算出的反元素称为d。
生成RSA密钥的算法
我们需要两个主要的算法来使用Python生成RSA密钥:Cryptomath模块和Rabin Miller模块。
Cryptomath模块
遵循RSA算法所有基本实现的cryptomath模块的源代码如下:
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
RabinMiller模块
遵循RSA算法所有基本实现的RabinMiller模块的源代码如下:
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
生成RSA密钥的完整代码如下:
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()
输出
公钥和私钥已生成并分别保存到如下输出所示的文件中。
RSA密码加密
本章将重点介绍RSA密码加密的不同实现及其涉及的函数。您可以参考或包含此python文件来实现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"
我们已将哈希值初始化为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)
加密使用如下函数,该函数遵循RSA算法:
def encrypt(message, pub_key): cipher = PKCS1_OAEP.new(pub_key) return cipher.encrypt(message)
两个参数是必须的:message(消息)和pub_key(公钥)。公钥用于加密,私钥用于解密。
完整的加密过程程序如下:
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)
RSA密码解密
本章是上一章的延续,上一章逐步介绍了使用RSA算法进行加密的实现,并对其进行了详细讨论。
用于解密密文的函数如下:
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)
数字签名与发送方和接收方的详细信息一起进行验证。这增加了安全性。
RSA密码解密
您可以使用以下代码进行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)
破解RSA密码
使用小素数可以破解RSA密码,但是如果使用大素数,则被认为是不可能的。难以破解RSA密码的原因如下:
暴力破解无效,因为有太多可能的密钥需要尝试。而且,这会消耗大量时间。
字典攻击在RSA算法中无效,因为密钥是数字的,不包含任何字符。
字符的频率分析很难进行,因为单个加密块代表各种字符。
没有特定的数学技巧可以破解RSA密码。
RSA解密方程为:
M = C^d mod n
借助小素数,我们可以尝试破解RSA密码,相应的示例代码如下:
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()
输出
以上代码产生以下输出: