古典密码学有两种基本方法,置换密码和替代密码,置换密码指的是,密文和明文的字母是一样的,只是顺序不一样而已,而替代密码指的是,有一张对应的表,将明文中的字符替换成另一个字符。达到生成密文的效果。
替换密码
替换密码有凯撒密码,维吉尼亚密码,佛娜姆密码
置换密码
这里用到列置换密码
凯撒密码就是一个位移,根据给出的秘钥进行位移 下面是一种可能的代码
# 定义一个查询表
def encryption(str, k):
result = ""
for i in range(len(str)):
if str[i].isupper():
result += chr((ord(str[i]) + k - 65) % 26 + 65)
else:
result += chr((ord(str[i]) + k - 97) % 26 + 97)
return result
def decryption(str, k):
result = ""
for i in range(len(str)):
if str[i].isupper():
result += chr((ord(str[i]) - k - 65) % 26 + 65)
else:
result += chr((ord(str[i]) - k - 97) % 26 + 97)
return result
if __name__ == '__main__':
while True:
choice = input("加密or解密 a 加密 b 解密 c 退出\n")
if choice == 'a':
str = input("需要加密的字符串")
k = int(input("加密密钥"))
print("加密后的字符串为", encryption(str, k))
elif choice == 'b':
str = input("需要姐密的字符串")
k = int(input("解密密钥"))
print("解密后的字符串为", decryption(str, k))
elif choice == 'c':
break
else:
print("输入错误 重试")
continue
接下来是列变换代码
# 古典密码 置换密码 列置换密码
def substitution_cipher_encryption(plaintext, key):
# 列的个数
n = len(key)
# 行的个数 向上取整
m = -(-len(plaintext) // n)
# 然后生成m 行 n 列的矩阵 python是先写列再写行
matrix = [['' for i in range(n)] for j in range(m)]
# 明文填入矩阵中 长度不够填充为@
for i in range(len(plaintext)):
matrix[i // n][i % n] = plaintext[i]
for i in range(len(plaintext), m * n):
matrix[i // n][i % n] = '@'
# 按照秘钥中字符的相对顺序进行读取矩阵列数 比如说 秘钥是 bagc 那么读取顺序是1032
key_index = sorted(
range(n), key=lambda k: key[k]
) # 牛逼 我看不懂 我记得当时写哪个题去了 就是 bagc 他们原本位置是0123 排序后是1032 然后在原来对应数组填充1032
# 按读取顺序按列读取矩阵
ciphertext = ''
for i in key_index:
for j in range(m):
ciphertext += matrix[j][i]
return ciphertext
# 解密
def substitution_cipher_decryption(ciphertext, key):
n = len(key)
m = -(-len(ciphertext) // n)
key_index = sorted(range(n), key=lambda k: key[k])
# 因为我们这里没有去除空格密文一定是m行n列的 所以我们先成矩阵m行n列
matrix = [['' for i in range(n)] for j in range(m)]
index = 0
# 然后按照秘钥的顺序填充矩阵 比如说秘钥是1032 密文是bfcgdhhaee 因为有m行,所以我们每次将m个字符填充 先将bf 填充到矩阵的第一列 cg填充进第0列 以此类推
for i in key_index:
for j in range(m):
matrix[j][i] = ciphertext[index]
index += 1
# 然后按照行读取矩阵
plaintext = ''
for i in range(m):
for j in range(n):
plaintext += matrix[i][j]
# 去除填充的@
plaintext = plaintext.replace('@', '')
return plaintext
if __name__ == '__main__':
# 1. 置换密码
# 明文
# 输入秘钥
while (True):
choice = input("请输入你的选择:\n1.加密\n2.解密\n 3.退出\n")
if choice == '1':
plaintext = input("请输入明文:")
key = input("请输入秘钥:")
# 加密
ciphertext = substitution_cipher_encryption(plaintext, key)
print("密文为:", ciphertext)
continue
elif choice == '2':
ciphertext = input("请输入密文:")
key = input("请输入秘钥:")
# 解密
plaintext = substitution_cipher_decryption(ciphertext, key)
print("明文为:", plaintext)
continue
elif choice == '3':
break
else:
print("输入错误,请重新输入")
continue
列变换就是根据给出的秘钥然后进行读取,解密同理