密码学上的经典瞬间:如果当时有Python

提到"安全",首先想到的一定是加密。

在如今的互联网环境中,信息加密无处不在,我们早已习惯,甚至毫无感觉。

比如,通过https协议访问的各个网站的内容,QQ,微信等聊天工具之间互相发送的信息等等,都是经过加密处理的。

前几天看了一篇介绍密码学历史的文章,原来密码学的历史可以追溯到古罗马时代,

学习python时,可以用这些历史上红极一时的经典加密方法来练练手,

练习python的同时,也看看前人在密码学上表现的智慧。

凯撒加密

凯撒加密(Caesar Shift)是第一个已知的密码学实例,看名字就知道可能来自古罗马。

这是由罗马皇帝朱利尤斯·凯撒(Julius Caesar)发明的,用于当时的战时秘密通信。

原理非常简单,就是将每个字母向后移动两位,比如**"A"变成 "C" "B"变成 "D"**等等。

所以,只要将所有可能出现的字母和符号罗列出来,很容易用python实现。

python 复制代码
all_chars = """abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.?:;'"\n """

def change(c, shift=2):
    idx = all_chars.index(c)
    return all_chars[(idx+shift)%len(all_chars)]

def caesar_encrypt(s, shift=2):
    """
    加密,默认后移两位
    """
    chars = [change(c, shift) for c in s]
    return "".join(chars)

def caesar_decrypt(s, shift=-2):
    """
    解密,默认前移两位
    """
    chars = [change(c, shift) for c in s]
    return "".join(chars)

origin_msg = "Attack at nine o 'clock tomorrow morning"
print("原始信息: {}".format(origin_msg))

secret_msg = caesar_encrypt(origin_msg)
print("加密信息: {}".format(secret_msg))
print("解密信息: {}".format(caesar_decrypt(secret_msg)))

# 运行结果
原始信息: Attack at nine o 'clock tomorrow morning
加密信息: Cvvcembcvbpkpgbqb
enqembvqoqttqyboqtpkpi
解密信息: Attack at nine o 'clock tomorrow morning

这种加密方式适合英文字母(字母的数量不大),如果用中文的话,就不太适用了(汉字的数量太多了)。

凯撒加密现在看来实在太简陋,借助计算机来暴力破解,很快就能解密,不过在古代,还是非常有效的。

二战时德国的恩尼格玛

恩尼格玛Enigma)是二战时期德国使用的一种密码机,它在密码学历史上扮演了重要角色。

它借助机械来加密,看起来像一台装满电器元件的打字机,使用了"字母轮"装置,可以进行数百万次的字母置换,生成一组随机的、无模式的字母串。

在二战期间,恩尼格玛 被德国军队广泛使用,包括空军、海军和陆军,德国对恩尼格玛 进行了多次改进,增加了其安全性。

后来,英国的图灵Alan Turing )领导了一个团队,设计了一种名为**"彭姆斯特号"**的机器,成功破译了恩尼格玛密码。

这一成就对盟军在二战中的胜利起到了重要作用,通过破译恩尼格玛密码,盟军能够获取德国的军事机密信息,从而在战场上取得优势。

IT行业的人,应该没人不知道图灵的吧。有一部名叫《模仿游戏》的电影描述的就是这个事迹,非常精彩。

恩尼格玛 密码机的工作原理是通过一系列齿轮或转子,其位置决定替换密码。

关于其细节有很多专业的文章介绍,这里参考网络上的代码实现了一个简易版本(能够支持大小写字母的加密和恢复)。

python 复制代码
from random import shuffle, randint, choice
from copy import copy

num_alphabet = list(range(26))


def en_shift(l, n):
    return l[n:] + l[:n]


class Cog:
    """
    模拟转子
    """
    def __init__(self):
        self.shuf = copy(num_alphabet)
        shuffle(self.shuf)
        return

    def subs_in(self, i):
        return self.shuf[i]

    def subs_out(self, i):
        return self.shuf.index(i)

    def rotate(self):
        self.shuf = en_shift(self.shuf, 1)

    def setcog(self, a):
        self.shuf = a


class Enigma:
    def __init__(self, numcogs, readability=True):
        self.readability = readability
        self.numcogs = numcogs
        self.cogs = []
        self.oCogs = []

        for i in range(0, self.numcogs):
            self.cogs.append(Cog())
            self.oCogs.append(self.cogs[i].shuf)

        refabet = copy(num_alphabet)
        self.reflector = copy(num_alphabet)
        while len(refabet) > 0:
            a = choice(refabet)
            refabet.remove(a)

            b = choice(refabet)
            refabet.remove(b)

            self.reflector[a] = b
            self.reflector[b] = a

    def reset(self):
        for i in range(0, self.numcogs):
            self.cogs[i].setcog(self.oCogs[i])

    def encode(self, text):
        t = 0
        ciphertext = ""
        for l in text:
            c = ord(l)
            start_c = 65
            if c >= 97:
                start_c = 97

            num = c % start_c
            if num > 25 or num < 0:
                if self.readability:
                    ciphertext += l
                else:
                    pass

            else:
                # Pass through cogs, reflect, then return through cogs
                t += 1
                for i in range(self.numcogs):
                    num = self.cogs[i].subs_in(num)

                num = self.reflector[num]

                for i in range(self.numcogs):
                    num = self.cogs[self.numcogs - i - 1].subs_out(num)
                ciphertext += "" + chr(start_c + num)

                # Rotate cogs
                for i in range(self.numcogs):
                    if t % ((i * 6) + 1) == 0:
                        self.cogs[i].rotate()
        return ciphertext

# 初始化
x = Enigma(6)

origin_msg = "Attack at nine o 'clock tomorrow morning"
print("原始信息: {}".format(origin_msg))

secret_msg = x.encode(origin_msg)
print("加密信息: {}".format(secret_msg))

x.reset()
print("解密信息: {}".format(x.encode(secret_msg)))

# 运行结果
原始信息: Attack at nine o 'clock tomorrow morning
加密信息: Gpzlwo ub heck w 'ewrfo ufvpvlnj ergaaki
解密信息: Attack at nine o 'clock tomorrow morning

这里初始化了6个转子,恩尼格玛 密码机即使针对相同的原始消息 ,每次运行产生的加密信息 都不一样,

大大增加了破解的难度。

有计算机之后

有了计算机之后,加密和解密的能力都大大增强了,目前用的最多也是最安全的当属RSA算法,
RSA的安全性依赖于大数分解的难度,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还未被破解,至少目前尚未有人公开宣布。

RSA算法在各种编程语言中都有相应的库,这里不在重复实现了。

相关推荐
哆啦A梦的口袋呀4 分钟前
基于Python学习《Head First设计模式》第六章 命令模式
python·学习·设计模式
努力搬砖的咸鱼6 分钟前
从零开始搭建 Pytest 测试框架(Python 3.8 + PyCharm 版)
python·pycharm·pytest
Calvex8 分钟前
PyCharm集成Conda环境
python·pycharm·conda
一千柯橘20 分钟前
python 项目搭建(类比 node 来学习)
python
sduwcgg25 分钟前
python的numpy的MKL加速
开发语言·python·numpy
大模型真好玩26 分钟前
可视化神器WandB,大模型训练的必备工具!
人工智能·python·mcp
东方佑28 分钟前
使用 Python 自动化 Word 文档样式复制与内容生成
python·自动化·word
代码搬运媛28 分钟前
React 中 HTML 插入的全场景实践与安全指南
安全·react.js·html
钢铁男儿34 分钟前
Python 接口:从协议到抽象基 类(定义并使用一个抽象基类)
开发语言·python
databook42 分钟前
当机器学习遇见压缩感知:用少量数据重建完整世界
python·机器学习·scikit-learn