Skip to main content

第一课:密码学入门

(一)配置Python 环境

Python 的前置安装步骤看这里:安装 Python | HeiheT09 的技术笔记

新建一个虚拟环境 crpt

python3 -m venv crpt

激活该环境

source crpt/bin/activate

安装需要的模块

pip install cryptography
apt install libmpfr-dev libmpc-dev libgmp-dev python3-gmpy2
pip install gmpy2


(二)凯撒密码

1. 凯撒密码

ASCLL 表中的数字依次循环位移,非字母保持不变

练习:凯撒密码加密和解密:

def caesar_encrypt(text, shift):
    encrypted_text = ""
    for char in text:
        if char.isalpha():
            shift_amount = shift % 26
            if char.islower():
                encrypted_text += chr((ord(char) - ord('a') + shift_amount) % 26 + ord('a'))
            elif char.isupper():
                encrypted_text += chr((ord(char) - ord('A') + shift_amount) % 26 + ord('A'))
        else:
            encrypted_text += char
    return encrypted_text


def caesar_decrypt(text, shift):
    return caesar_encrypt(text, -shift)


# 示例用法
if __name__ == "__main__":
    message = "Hello, World!"
    shift = 3
    encrypted = caesar_encrypt(message, shift)
    decrypted = caesar_decrypt(encrypted, shift)
    print(f"原始消息: {message}")
    print(f"加密消息: {encrypted}")
    print(f"解密消息: {decrypted}")

凯撒密码的破解方法:

对字符串进行25次位移,穷尽式列举,然后与大字典对比,统计单词出现次数,得到最高概率的一个

2. 替换密码

凯撒密码升级版:替换密码

也就是使用打乱的加密字典来替换原字符,而不是使用整体位移

from collections import Counter

def decrypt_substitution_cipher(encrypted_text, substitution_dict):
    reverse_dict = {v: k for k, v in substitution_dict.items()}
    decrypted_text = ""
    for char in encrypted_text:
        if char in reverse_dict:
            decrypted_text += reverse_dict[char]
        else:
            decrypted_text += char
    return decrypted_text

# 示例加密字典
substitution_dict = {
    'a': 'z', 'b': 'y', 'c': 'x', 'd': 'w', 'e': 'v', 'f': 'u', 'g': 't',
    'h': 's', 'i': 'r', 'j': 'q', 'k': 'p', 'l': 'o', 'm': 'n', 'n': 'm',
    'o': 'l', 'p': 'k', 'q': 'j', 'r': 'i', 's': 'h', 't': 'g', 'u': 'f',
    'v': 'e', 'w': 'd', 'x': 'c', 'y': 'b', 'z': 'a'
}

# 加密的消息
encrypted_message = "gsv jfrxp yildm ulc qfnkh levi gsv ozab wlt"

# 解密
decrypted_message = decrypt_substitution_cipher(encrypted_message, substitution_dict)
print(f"解密消息: {decrypted_message}")


替换密码的破解:

替换密码的字典一共有:26!=26×25×24×…×2×1 = 4.03×10^26 种,显然暴力破解已经不现实

在不知道替换字典的情况下破解替换密码,可以使用 频率分析法

  1. 统计加密文本中每个字母出现的频率

  2. 在英文文章中同样也会有每个字母出现的频率,大概的排名如下:

    • E, T, A, O, I, N, S, H, R, D, L, C, U, M, W, F, G, Y, P, B, V, K, J, X, Q, Z
  3. 按照出现频率一一对应推断替换关系。


但是这样得到的结果仍然不准确,事实上,替换密码的破解还需要人工结合一些语言学常识来进行,可以参照这篇博文

【密码学】利用用频率分析破译替换密码_频率分析法解密-CSDN博客

此外有个有用的工具可以进行自动分析替换。就是 SubstitutionBreaker

pip install subbreaker

使用秘钥加密

subbreaker encode --key ZEBRASCDFGHIJKLMNOPQTUVWXY --text "flee at once. we are discovered!"

使用秘钥解密

subbreaker decode --key ZEBRASCDFGHIJKLMNOPQTUVWXY --text "siaa zq lkba. va zoa rfpbluaoar!"

在不知道密钥的情况下破解密码:

subbreaker break --lang EN --text \
"Rbo rpktigo vcrb bwucja wj kloj hcjd, km sktpqo, cq rbwr loklgo
> vcgg cjqcqr kj skhcja wgkja wjd rpycja rk ltr rbcjaq cj cr.
> -- Roppy Lpwrsborr"

输出

Alphabet: abcdefghijklmnopqrstuvwxyz
Key: wisdomabcefghjklzpqrtuvxyn
Fitness: 103.68
Nbr keys tried: 95875
Keys per second: 102780
Execution time (seconds): 0.933
Plaintext:
The trouble with having an open mind, of course, is that people
> will insist on coming along and trying to put things in it.
> -- Terry Pratchett

(三)浅谈密码学

密码学主要有三个目的

  1. 机密性 :只有授权方才能阅读被保护的信息
  2. 身份验证