密码学的英语单词是 Cryptograghy,由希腊单词 Kryptos(隐藏)和 Graphin (写)派生出来,最初代表的意思是用来隐秘的传递信息。

以时间划分,1976年以前的密码算法都属于 古典密码学,古典密码学现在已经很少采用了,然而,研究古典密码的原理对于理解构造和分析现代密码都是十分有益的。古典密码学中最经典的两种算法如下:

  • 替代法

    系统地将一组字母换成其他字母或符号,例如 fly 变成 gmz (每个字母用下一个字母取代)

  • 移位法

    将字母顺序重新排列,例如 help 变成 ehpl

凯撒密码

凯撒密码(Caesar cipher)是最经典的替代法,据传由古罗马帝国的皇帝凯撒所发明,用在与远方将领的通讯上,每个字母被往后位移三格字母所替代

如果信息需要保密,信中便使用暗号,也即是改变字母顺序,使用字母 D 代替 A,以此类推,使局外人无法组成一个单词。

不过,使用多次使用凯撒密码来加密并不能获得更大的安全性,因为使用偏移量 A 加密得到的结果再用偏移量 B 加密,等同于使用 A+B 的偏移量进行加密的结果

Python 实现凯撒密码

def encrypt_text(origin, key=3):
    """ @origin: 初始字符串 @key: 字母位移次数 """
    result_text = ''
    for char in origin:
        ascii_code = ord(char)+key  # 获取字符的ASCII码并移动指定位数
        result_text += chr(ascii_code)  # 将移动后的ASCII码转换至字符并拼接
    return result_text

# 初始需要加密的字符串
origin_text = 'Python is powerful... and fast,plays well with others, runs everywhere,is friendly and easy to learn,is Open.'

指定偏移量为 3,加密原文:

origin_en = encrypt_text(origin_text, 3)

#S|wkrq#lv#srzhuixo111#dqg#idvw/sod|v#zhoo#zlwk#rwkhuv/#uxqv#hyhu|zkhuh/lv#iulhqgo|#dqg#hdv|#wr#ohduq/lv#Rshq1

指定偏移量为 -3,解密数据

origin_de = encrypt_text(origin_en, -3)

# Python is powerful... and fast,plays well with others, runs everywhere,is friendly and easy to learn,is Open.

破解凯撒密码

由于使用凯撒密码进行加密的语言一般都是字母文字系统,因此密码中可能使用的偏移量也是有限的。例如使用 26 个字母的英语,它的偏移量最多就是 25(偏移量 26 等同于偏移量 0;偏移量超过 26,等同于偏移量 1-25),因此可以通过穷举法,轻易地进行破解。

另一种方法是通过频率分析,当密文长度足够大的情况下,可以先分析密文中每个字母出现的频率,然后将这一频率与正常情况下的该语言字母表中所有字母出现的频率作比较。例如在英语中,正常明文中字母 e 和 t 出现的频率特别高。通过这一特点,分析密文字母出现的频率,可以估计出正确的偏移量。

但是频率分析也有其局限性,它对于故意省略元音字母或者其他缩写方式写成的明文加密出来的密文并不适用。

使用 Python 实现破解过程

import random

def encrypt_text(origin, key=3):
    """ @origin: 初始字符串 @key: 字母位移次数 """
    result_text = ''
    for char in origin:
        ascii_code = ord(char)+key  # 获取字符的ASCII码并移动指定位数
        result_text += chr(ascii_code)  # 将移动后的ASCII码转换至字符并拼接
    return result_text

def decrypt_text(text):
    # 1. 统计密文中字符的出现次数
    dct = {
   }
    for char in text:
        dct[char] = dct.get(char, 0) + 1

    # 2. 对字典排序
    dct = dict(sorted(dct.items(), key=lambda x: x[1], reverse=True))
    
    # 3. 取出出现次数最多的7个元素, 得出与字母 e 的偏移量
    for item in list(dct)[:7]:
        key = ord('e') - ord(item)
        pred_text = encrypt_text(text, key)
        print(f'偏移量 = {key}:')
        print("\t"+pred_text)

# 初始需要加密的字符串
origin_text = 'Python is powerful... and fast,plays well with others, runs everywhere,is friendly and easy to learn,is Open.'
# 随机指定偏移量
en_text = encrypt_text(origin_text, random.randint(1, 20))

# 开始解密
decrypt_text(en_text)

结果如下: