一、原理
凯撒密码 是密码学中的一种简单的替换加密技术。明文中的所有字符都会替换为其按照字母表顺序向左(或向右)偏移一定量后得到的新字母,作为加密后密文。
如当偏移量为 3 时,明文中所有的字母 A 将被替换成字母 D,B 替换成 E,以此类推。
若收到密文的同时已知加密时使用的偏移量,就可以快速地通过逆运算获取到最初的明文。
下面两张图展示了当偏移量为 8 时明文字母与密文字母的对应关系(图一即凯撒密码轮盘,外层为明文,内层为密文,可旋转以改变偏移量)以及实际的加密过程(图二):
PS:对一段明文消息连续应用多个不同的偏移量进行凯撒密码规则的加密,并不会增强安全等级。即轮盘的多次旋转,实际上等同于抵消后的一次旋转。多次应用的不同偏移量,最终等同于抵消后的一次偏移量,对于暴力破解来说并不会增加复杂度。
如第一次对明文实施偏移 3 位的凯撒加密,再对生成的密文实施偏移 10 位的加密,实际上相当于对最初的明文实施了偏移 13 位的加密。
二、Python 实现凯撒密码
源代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14while True:
key = input("Please input a key number (like 13):\n") or 13
mode = input("\nPlease input mode (encrypt or decrypt):\n") or "encrypt"
symbols = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 !?.'
# 根据数字 key 对字母表 symbols 进行偏移操作,形成密文字母表 ciphers
ciphers = symbols[int(key):] + symbols[:int(key)]
# 根据加密与解密动作,生成明文字母到密文字母(或密文到明文)的对应关系
transtab = str.maketrans(symbols, ciphers) if mode == 'encrypt' else str.maketrans(ciphers, symbols)
message = input("\nPlease input plaintext or ciphertext:\n")
# 完成明文到密文(或密文到明文)的转换
result = message.translate(transtab)
print(f"\nThe result is: {result}\n\n")
运行效果如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22Please input a key number (like 13):
13
Please input mode (encrypt or decrypt):
encrypt
Please input plaintext or ciphertext:
This is my secret message.
The result is: guv6Jv6Jz!J6rp5r7Jzr66ntrM
Please input a key number (like 13):
13
Please input mode (encrypt or decrypt):
decrypt
Please input plaintext or ciphertext:
guv6Jv6Jz!J6rp5r7Jzr66ntrM
The result is: This is my secret message.
三、Python 对凯撒密码的爆破
即在加密用的 key 值未知的情况下,尝试所有可能的 key 值(0 到字母表长度减一)对密文进行解密,输出以查看解密出的明文是否有意义。
源代码:1
2
3
4
5
6
7
8
9
10
11symbols = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 !?.'
ciphertext = input("Please input ciphertext:\n")
for key in range(len(symbols)):
ciphers = symbols[key:] + symbols[:key]
transtab = str.maketrans(ciphers, symbols)
plaintext = ciphertext.translate(transtab)
print(f'Key #{key}: {plaintext}')
运行效果如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Please input ciphertext:
guv6Jv6Jz!J6rp5r7Jzr66ntrM
Key #0: guv6Jv6Jz!J6rp5r7Jzr66ntrM
Key #1: ftu5Iu5Iy I5qo4q6Iyq55msqL
Key #2: est4Ht4Hx0H4pn3p5Hxp44lrpK
Key #3: drs3Gs3Gw9G3om2o4Gwo33kqoJ
Key #4: cqr2Fr2Fv8F2nl1n3Fvn22jpnI
Key #5: bpq1Eq1Eu7E1mkzm2Eum11iomH
Key #6: aopzDpzDt6Dzljyl1DtlzzhnlG
Key #7: ZnoyCoyCs5CykixkzCskyygmkF
Key #8: YmnxBnxBr4BxjhwjyBrjxxfljE
Key #9: XlmwAmwAq3AwigvixAqiwwekiD
Key #10: Wklv.lv.p2.vhfuhw.phvvdjhC
Key #11: Vjku?ku?o1?ugetgv?oguucigB
Key #12: Uijt!jt!nz!tfdsfu!nfttbhfA
Key #13: This is my secret message.
Key #14: Sghr0hr0lx0rdbqds0ldrrZfd?
Key #15: Rfgq9gq9kw9qcapcr9kcqqYec!
...