目录
凯撒密码
对于凯撒密码的加密,我们需要将明文中的每个字母向后移动一定的位置。移动的位置数即为密钥。例如,如果密钥为3,则字母A将被替换为D,字母B将被替换为E,以此类推。
def caesar_encrypt(plaintext, key):
ciphertext = ""
for char in plaintext:
if char.isalpha(): # 只加密字母字符
if char.isupper():
ciphertext += chr((ord(char) - ord('A') + key) % 26 + ord('A'))
else:
ciphertext += chr((ord(char) - ord('a') + key) % 26 + ord('a'))
else:
ciphertext += char
return ciphertext
def caesar_decrypt(ciphertext, key):
plaintext = ""
for char in ciphertext:
if char.isalpha(): # 只解密字母字符
if char.isupper():
plaintext += chr((ord(char) - ord('A') - key) % 26 + ord('A'))
else:
plaintext += chr((ord(char) - ord('a') - key) % 26 + ord('a'))
else:
plaintext += char
return plaintext
# 用户输入明文和密钥
plaintext = input("请输入明文: ")
key = int(input("请输入密钥: "))
ciphertext = caesar_encrypt(plaintext, key)
print("加密后:", ciphertext)
decrypted_text = caesar_decrypt(ciphertext, key)
print("解密后:", decrypted_text)
- 运行结果如下,运行工具为pycharm :
维吉尼亚密码
维吉尼亚密码是一种多表替换密码,其基本原理是使用一个密钥来对明文进行加密。密钥的长度与明文相同,每个密钥字符对应明文中的一个字符。
- 举例说明:
假如我要加密一段明文
明文:HiJANE
密匙:FAR
密文:MIAFNV
- 加密过程如下:
根据上面的维吉尼亚密码表,上面的一行为密匙,然后左边的一列为明文,原理就是根据密匙来对照列找所对应明文的字母。
明文为HIJANE,对应的密匙为FAR,那么就是FARFAR,在第一行密匙找到F,第一列明文找到H,在表中对应的值为”M“,以此类推,得到密文为:MIAFNV。
- 加解密代码如下:
def vigenere_encrypt(plaintext, key):
ciphertext = ""
key = key.upper() # 将密钥转为大写
key_len = len(key)
for i in range(len(plaintext)):
char = plaintext[i]
if char.isalpha(): # 只加密字母字符
if char.isupper():
offset = ord('A')
else:
offset = ord('a')
key_shift = ord(key[i % key_len]) - ord('A') # 密钥中对应字母的移位数
shifted_char = chr((ord(char) - offset + key_shift) % 26 + offset)
ciphertext += shifted_char
else:
ciphertext += char
return ciphertext
def vigenere_decrypt(ciphertext, key):
plaintext = ""
key = key.upper() # 将密钥转为大写
key_len = len(key)
for i in range(len(ciphertext)):
char = ciphertext[i]
if char.isalpha(): # 只解密字母字符
if char.isupper():
offset = ord('A')
else:
offset = ord('a')
key_shift = ord(key[i % key_len]) - ord('A') # 密钥中对应字母的移位数
shifted_char = chr((ord(char) - offset - key_shift) % 26 + offset)
plaintext += shifted_char
else:
plaintext += char
return plaintext
# 用户输入明文和密钥
plaintext = input("请输入明文: ")
key = input("请输入密钥: ")
ciphertext = vigenere_encrypt(plaintext, key)
print("加密后:", ciphertext)
decrypted_text = vigenere_decrypt(ciphertext, key)
print("解密后:", decrypted_text)
- 代码运行结果:
栅栏密码
栅栏密码是一种简单的加密算法,可以通过将明文按照一定规则排列成一个矩阵,然后按照特定顺序读取矩阵中的字符来进行加密。
栅栏密码的加密过程是按照特定的划分规则进行的,这个规则决定了字符在网格中的填充路径。
在栅栏密码中,栅栏数决定了网格的行数。对于栅栏数为 n 的情况,网格就会有 n 行。
加密过程按照以下规则进行:
- 以从上到下、从左到右的顺序将明文字符填充到网格中。
- 当填充到最底行时,改变方向,开始往上填充字符。
- 当填充到最顶行时,再次改变方向,继续往下填充字符。
- 重复以上步骤,直到所有字符都被填充到网格中。
这样的划分规则能够确保明文字符按照一定的路径被排列在网格中,从而形成密文。
以WHATYOURNAME为例,栅栏数为 3,所以网格有 3 行。按照规则,我们将 "WHATYOURNAME" 中的字符依次填充到网格中,得到如下的网格:
['W', '', '', '', 'Y', '', '', '', 'N', '', '', '']
['', 'H', '', 'T', '', 'O', '', 'R', '', 'A', '', 'E']
['', '', 'A', '', '', '', 'U', '', '', '', 'M', '']
按行读取网格中的字符即可获得密文 "WYNHTORAEAUM"。
代码如下:
def rail_fence_cipher_encrypt(plaintext, num_rails):
# 创建一个空的网格
grid = [[''] * len(plaintext) for _ in range(num_rails)]
# 根据划分规则,依次填充字符到网格中
row = 0
direction = 1
for i in range(len(plaintext)):
grid[row][i] = plaintext[i]
row += direction
if row == 0 or row == num_rails - 1:
direction *= -1
# 按行读取网格中的字符,得到密文
ciphertext = ''
for i in range(num_rails):
for j in range(len(plaintext)):
if grid[i][j] != '':
ciphertext += grid[i][j]
return ciphertext
# 用户输入明文和栅栏数
plaintext = input("请输入明文:")
num_rails = int(input("请输入栅栏数:"))
# 加密明文
ciphertext = rail_fence_cipher_encrypt(plaintext, num_rails)
print("密文:" + ciphertext)
- 运行结果:
- 解密过程代码如下
def decrypt_fence_cipher(ciphertext, rails):
# 创建一个空的二维列表来存储栅栏密文字符
fence = [['' for _ in range(len(ciphertext))] for _ in range(rails)]
# 根据栅栏规则填充栅栏列表
rail = 0
direction = 1
for i in range(len(ciphertext)):
fence[rail][i] = '*'
rail += direction
# 栅栏到达边界时改变方向
if rail == 0 or rail == rails - 1:
direction *= -1
# 将密文字符替换为栅栏字符
index = 0
for i in range(rails):
for j in range(len(ciphertext)):
if fence[i][j] == '*':
fence[i][j] = ciphertext[index]
index += 1
# 创建一个与密文长度相同的空字符串,用于存储解密后的明文
plaintext = ''
# 按照栅栏规则读取栅栏列表,获取明文
rail = 0
direction = 1
for i in range(len(ciphertext)):
plaintext += fence[rail][i]
rail += direction
# 栅栏到达边界时改变方向
if rail == 0 or rail == rails - 1:
direction *= -1
return plaintext
# 获取用户输入的密文和栅栏数
ciphertext = input("请输入栅栏密码密文: ")
rails = int(input("请输入栅栏数: "))
# 解密密文
plaintext = decrypt_fence_cipher(ciphertext, rails)
print("解密结果:", plaintext)
- 运行结果如下:
Playfair密码
Playfair密码要求明文长度为偶数,将明文字母按两个字母一组分成若干个单元,然后将这些单元替换成密文字母组合,替换时基于一个5×5字母矩阵,该矩阵使用一个选定的关键词(密钥)来构造,构造方法如下:
从左到右,从上到下一次填入关键词(密钥)的字母,若关键词中有重复字母,则第二次出现时略过,然后将26个英文字母中剩下的字母按字母顺序填入矩阵中,其中字母 i 和 j 看作是同一个字符。同时约定规则——表中的第一列看作是第五列的右边一列,第一行看作第五行的下一行,即无边界可循环。
对每一对明文字母P1,P2,加密时根据它们在5×5字母矩阵中的位置分别处理如下:
- 若P1,P2在同一行,则对应的密文分别是紧靠P1,P2右端的字母。
- 若P1,P2在同一列,则对应的密文分别是紧靠P1,P2下端的字母
- 若P1,P2不在同一行,也不在同一列,则对应的密文以P1,P2为对顶角确定的矩形的两外两个顶点的字母,按同行的原则对应。
- 若P1,P2相同,则在P1,P2中间插入一个约定好的字母(如X),并用上述方法处理。
- 若名文字母数为奇数,则在明文的末端添加一个事先约定好的字母进行填充(如X)。
- 举例说明:
设密钥为“ISCBUPT”,则根据字母矩阵创建规则创建的字母矩阵如下:
若明文为"steganographia",则首先把明文分为两个字母一组,然后对两个一组的明文分别加密:
st | eg | an | og | ra | ph | ia |
TG | TL | TO | NH | OE | AF | CP |
由此得密文为:TGTLTONHOEAFCP。
加密代码如下:
def generate_matrix(key):
# 生成Playfair密码矩阵
alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
key = key.upper().replace("J", "I") # 将J替换为I
key_set = set(key)
matrix = []
for letter in key:
if letter not in matrix:
matrix.append(letter)
for letter in alphabet:
if letter not in key_set and letter not in matrix:
matrix.append(letter)
matrix = [matrix[i:i + 5] for i in range(0, 25, 5)]
return matrix
def find_position(matrix, letter):
# 在矩阵中查找字母的位置
for i in range(5):
for j in range(5):
if matrix[i][j] == letter:
return i, j
def encrypt(plaintext, key: str) -> str:
# 生成Playfair密码矩阵
matrix = generate_matrix(key)
# 将明文分组并加密
ciphertext = ""
plaintext = plaintext.upper().replace("J", "I") # 将J替换为I
plaintext = "".join([i for i in plaintext if i.isalpha()]) # 去除非字母字符
plaintext += "X" * (len(plaintext) % 2) # 补齐成偶数长度
for i in range(0, len(plaintext), 2):
pair = plaintext[i:i + 2]
row1, col1 = find_position(matrix, pair[0])
row2, col2 = find_position(matrix, pair[1])
if row1 == row2:
ciphertext += matrix[row1][(col1 + 1) % 5] + matrix[row2][(col2 + 1) % 5]
elif col1 == col2:
ciphertext += matrix[(row1 + 1) % 5][col1] + matrix[(row2 + 1) % 5][col2]
else:
ciphertext += matrix[row1][col2] + matrix[row2][col1]
return ciphertext
# 提示用户输入明文和密钥
plaintext = input("请输入明文:")
key = input("请输入密钥:")
# 加密并输出密文
ciphertext = encrypt(plaintext, key)
print("密文:", ciphertext)
- 运行结果如下:
- 解密算法如下:
def generate_matrix(key):
# 生成Playfair密码矩阵
alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
key = key.upper().replace("J", "I") # 将J替换为I
key_set = set(key)
matrix = []
for letter in key:
if letter not in matrix:
matrix.append(letter)
for letter in alphabet:
if letter not in key_set and letter not in matrix:
matrix.append(letter)
matrix = [matrix[i:i + 5] for i in range(0, 25, 5)]
return matrix
def find_position(matrix, letter):
# 在矩阵中查找字母的位置
for i in range(5):
for j in range(5):
if matrix[i][j] == letter:
return i, j
def decrypt(ciphertext, key):
# 生成Playfair密码矩阵
matrix = generate_matrix(key)
# 解密密文
plaintext = ""
for i in range(0, len(ciphertext), 2):
pair = ciphertext[i:i + 2]
row1, col1 = find_position(matrix, pair[0])
row2, col2 = find_position(matrix, pair[1])
if row1 == row2:
plaintext += matrix[row1][(col1 - 1) % 5] + matrix[row2][(col2 - 1) % 5]
elif col1 == col2:
plaintext += matrix[(row1 - 1) % 5][col1] + matrix[(row2 - 1) % 5][col2]
else:
plaintext += matrix[row1][col2] + matrix[row2][col1]
return plaintext
# 提示用户输入密文和密钥
ciphertext = input("请输入密文:")
key = input("请输入密钥:")
# 解密并输出明文
plaintext = decrypt(ciphertext, key)
print("明文:", plaintext)
- 运行结果如下: