Cryptography With Python 简明教程
Cryptography with Python - Overview
Double Strength Encryption
Python Overview and Installation
Python 是一种开源脚本语言,它高级、直譯、互动且面向对象的。它被设计为高度可读。Python 语言的语法易于理解且经常使用英语关键字。
Key Points of Python Language
Python 编程语言的关键点如下 −
-
它包括面向对象的编程方法以及函数式和结构化编程和方法。
-
它既可用作脚本语言,也可用作编程语言。
-
它包括自动垃圾回收。
-
它包括高级动态数据类型并支持各种动态类型检查。
-
Python 包括与 C、C++ 和 Java 等语言集成的功能。
Python 语言的下载链接如下 − www.python.org/downloads 它包括 Windows、MacOS 和 Linux 发行版等各种操作系统的软件包。
Python Lists
Python 列表可以声明为复合数据类型,用逗号分隔并用方括号 ([]) 括起来。
list = [ 'abcd', 786 , 2.23, 'john', 70.2 ]
tinylist = [123, 'john']
Cryptography with Python - Reverse Cipher
上一章概述了如何在本地计算机上安装 Python。在本章中,你将详细了解反向密码及其编码。
Algorithm of Reverse Cipher
反向密码算法具有以下特征:
-
* 反向密码使用反转明文串的模式来转换为密文串。
-
* 加密和解密的过程相同。
-
* 若要解密密文,用户只需反转密文即可获得明文。
Drawback
-
反向密码的主要缺点是它非常弱。黑客可以轻松破解密文以获取原始消息。因此,反向密码不被认为是维护安全通信通道的良好选择。
Example
考虑一个示例,该示例中将使用反向密码算法实现语句 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)
Cryptography with Python - Caesar Cipher
在上一章中,我们已经处理了反向密码。本章详细介绍了凯撒密码。
Algorithm of Caesar Cipher
凯撒密码算法具有以下特征:
-
* 凯撒密码技术是一种简单易用的加密技术。
-
* 这是一种简单的替换密码。
-
* 明文的每个字母都被一个字母替换,该字母在字母表中的位置向下移动固定数量。
-
以下图表描述了凯撒密码算法实现的工作原理:
-
凯撒密码算法的程序实现如下:
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)
Hacking of Caesar Cipher Algorithm
密文可以用各种可能性破解。其中一种可能性是 Brute Force Technique, ,它涉及尝试每个可能的解密密钥。此技术不需要太多精力,对于黑客来说相对简单。
破解凯撒密码算法的程序实现如下−
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))
考虑在前一示例中加密的密文。然后,使用密钥并使用暴力攻击技术,可能的破解方法的输出如下−
Cryptography with Python - ROT13 Algorithm
到目前为止,您已经了解了反向密码和凯撒密码算法。现在,我们来讨论 ROT13 算法及其实现。
Explanation of ROT13 Algorithm
ROT13 密码指的是缩写 Rotate by 13 places 。它凯撒密码的一个特例,其中移位始终为 13。每封信都移位 13 位,以加密或解密消息。
Program Code
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 输出 -
Transposition Cipher
移位密码是一种密码算法,其中将明文中的字母顺序重新排列以形成密文。在此过程中,不包括实际的明文字母。
Example
移动密码的一个简单示例是 columnar transposition cipher ,其中明文中的每个字符都以指定的字母宽度水平书写。密文是垂直书写的,这会创建一个完全不同的密文。
考虑明文 hello world ,让我们应用如下所示的简单列移位技术
明文字符水平放置,并且密文以垂直格式创建为 : holewdlo lr. 。现在,接收者必须使用相同的表格将密文解密为明文。
Code
以下程序代码演示了列移位技术的简单实现−
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'))
Encryption of Transposition Cipher
在上一章中,我们学习了移位密码。在本章中,让我们讨论其加密。
Pyperclip
pyperclip 插件在 Python 编程语言中的主要用法是执行跨平台模块以将文本复制并粘贴到剪贴板中。你可以使用以下命令安装 Python pyperclip 模块
pip install pyperclip
如果系统中已存在该需求,则你可以看到以下输出−
Code
以下是使用 pyperclip 作为主模块的 Python 置换密码加密代码:
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()
Decryption of Transposition Cipher
在本章中,将学习解密置换密码的程序。
Code
观察以下代码以更好地理解如何解密置换密码。消息 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()
Encryption of files
在 Python 中,可以在传输到通信信道之前对文件进行加密和解密。为此,必须使用插件 PyCrypto 。可以使用以下给出的命令安装此插件。
pip install pycrypto
Code
使用密码保护对文件进行加密的程序代码如下所示:
# =================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
Decryption of files
在本章中,让我们讨论使用 Python 对密码学中的文件进行解密。请注意,对于解密过程,我们将遵循相同的过程,但不是指定输出路径,而是关注输入路径或加密的必要文件。
Code
以下是使用 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 Encoding and Decoding
Base64 编码将二进制数据转换为文本格式,该格式通过用户可以安全处理文本的通信通道传输。Base64 也称为 Privacy enhanced Electronic mail (PEM) ,主要用于电子邮件加密过程。
Python 包含一个名为 BASE64 的模块,其中包括两个主要函数,如下所示:-
-
base64.decode(input, output) - 它对指定的输入值参数进行解码,并将解码后的输出存储为对象。
-
Base64.encode(input, output) - 它对指定的输入值参数进行编码,并将编码后的输出存储为对象。
Program for Encoding
可以使用以下代码段执行 base64 编码:-
import base64
encoded_data = base64.b64encode("Encode this text")
print("Encoded text with base 64 is")
print(encoded_data)
Cryptography with Python - XOR Process
在本章节中,让我们了解 XOR 过程及其在 Python 中的编码。
Algorithm
加密和解密的 XOR 算法将明文转换为 ASCII 字节格式,并使用 XOR 过程将其转换为指定的字节。它为用户提供以下优势:-
-
Fast computation
-
左右侧没有标记区别
-
易于理解和分析
Code
可以使用以下代码段执行 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)
Multiplicative Cipher
在使用凯撒密码技术时,加密和解密符号涉及使用简单的基本加法或减法程序将值转换为数字。
如果使用乘法转换为密码文本,则称为 wrap-around 情况。请将字母和关联的数字考虑为以下所示−
这些数字将用于乘法程序,关联密钥为 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)
Note − 乘法密码的优点是它可以使用 8,953,851 之类的非常大的密钥。对于计算机而言,通过九百万个密钥中的大多数进行暴力攻击需要相当长的时间。
Cryptography with Python - Affine Cipher
Affine 密码是乘法密码和凯撒密码算法的组合。Affine 密码的基本实现如下图所示−
在本章中,我们将通过创建对应的类来实现 Affine 密码,该类包括用于加密和解密的两个基本函数。
Code
您可以使用以下代码来实现 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')
Hacking Monoalphabetic Cipher
在本章中,您将了解单表字母加密及其使用 Python 进行破解。
Monoalphabetic Cipher
单表字母加密对加密整个消息使用固定的替换。此处显示了使用带有 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)
Simple Substitution Cipher
简单替换密码是最常用的密码,包括用于将每个明文字符替换为每个密文字符的算法。在此过程中,与凯撒密码算法相比,字母顺序混乱。
Example
简单替换密码的密钥通常由 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()
Testing of Simple Substitution Cipher
在本章中,我们将专注于使用各种方法测试替换密码,这有助于生成随机字符串,如下所示 −
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()
Decryption of Simple Substitution Cipher
在本章中,您可以了解替换密码的简单实现,该实现根据简单替换密码技术中使用的逻辑显示加密和解密消息。这可以认为是编码的另一种方法。
Code
您可以使用以下代码执行使用简单替换密码的解密 −
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 Modules of Cryptography
在本章中,您将详细了解 Python 中加密的各种模块。
Cryptography Module
它包括所有配方和原语,并提供 Python 中的高级编码接口。您可以使用以下命令安装加密模块 −
pip install cryptography
Code
您可以使用以下代码实现加密模块 −
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)
Output
上面给出的代码生成以下输出了 −
这里给出的代码用于验证密码并创建其哈希。它还包括用于验证用于身份验证目的的密码的逻辑。
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')
Understanding Vignere Cipher
韦格纳密码加入了恺撒密码算法的微调,用于加密和解密。韦格纳密码与恺撒密码算法的工作方式相似,但有一个主要区别:恺撒密码包括一个字符偏移算法,而韦格纳密码则包括一个有多个字母偏移的密匙。
Mathematical Equation
对于加密,数学方程式如下:
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
韦格纳密码使用多套代换,因此也称为 polyalphabetic cipher 。韦格纳密码将使用字母密匙,而非数字密匙表示法:字母 A 将用于密匙 0,字母 B 将用于密匙 1,依次类推。加密过程前后字母的数字如下所示:
基于韦格纳密匙长度的密钥可能组合数目如下,它给出了韦格纳密码算法的安全性:
Implementing Vignere Cipher
在本章中,让我们了解韦格纳密码的实现方式。考虑要对文本 This is basic implementation of Vignere Cipher 进行编码,所使用的密钥为 PIZZA.
Code
可以使用以下代码在 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()
One Time Pad Cipher
Implementation of One Time Pad Cipher
Python 包含一个 hacky 实现模块,用于 one-time-pad 密码实现。该软件包名称称为一次性密码本,其中包含一个命令行加密工具,该工具使用类似一次性密码本密码算法的加密机制。
Symmetric and Asymmetric Cryptography
在本章中,让我们详细讨论对称和非对称密码术。
Symmetric Cryptography
在此类型中,加密和解密过程使用相同的密钥。它也被称为 secret key cryptography 。对称密码术的主要功能如下:
-
它更简单且速度更快。
-
这两个当事方以安全的方式交换密钥。
Data Encryption Standard (DES)
最流行的对称密钥算法是数据加密标准 (DES),且 Python 包含一个软件包,该软件包包括 DES 算法背后的逻辑。
Installation
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 算法实现所需的包,并以特定方式执行加密和解密。
Asymmetric Cryptography
它也被称为 public key cryptography. 。它的工作方式与对称加密相反。这意味着它需要两个密钥:一个用于加密,另一个用于解密。公钥用于加密,而私钥用于解密。
Drawback
-
由于密钥的长度,它导致加密速度较低。
-
Key management is crucial.
以下 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))
Understanding RSA Algorithm
Creating RSA Keys
在本章中,我们将重点介绍使用 Python 逐步实现 RSA 算法。
Generating RSA keys
涉及生成 RSA 密钥的步骤如下:
-
创建两个大素数,即 p 和 q 。这两个数字的积将被称为 n ,其中 n= p*q
-
生成与 (p-1) 和 (q-1). 互素的随机数。假设这个数被称为 e 。
-
计算 e 的模逆。计算所得的逆值将被称为 d 。
Algorithms for generating RSA keys
我们需要两个主算法才能使用 Python 生成 RSA 密钥—— Cryptomath module * and *Rabin Miller module 。
Cryptomath Module
遵循 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 Module
遵循 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 Cipher Encryption
在本章中,我们将重点介绍 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 Cipher Decryption
本章节是上一章节的续篇,在上一章节中我们遵循 RSA 算法逐步实现加密的步骤,并对此进行了详细探讨。
解密密文所用的函数如下 −
def decrypt(ciphertext, priv_key):
cipher = PKCS1_OAEP.new(priv_key)
return cipher.decrypt(ciphertext)
对于公钥密码术或非对称密钥密码术来说,保持两个重要特性很重要,即 Authentication 和 Authorization 。
Authorization
授权是确认发送者是唯一传输信息方的过程。以下代码对此进行了说明 −
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)
Authentication
身份验证可以利用下文说明的验证方法来实现 −
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 Cipher Decryption
你可以使用以下代码进行 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)
Hacking RSA Cipher
利用小素数有可能破解 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()