密码学上的经典瞬间:如果当时有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算法在各种编程语言中都有相应的库,这里不在重复实现了。

相关推荐
IT古董16 分钟前
【人工智能】Python在机器学习与人工智能中的应用
开发语言·人工智能·python·机器学习
Smartdaili China23 分钟前
如何在 Microsoft Edge 中设置代理: 快速而简单的方法
前端·爬虫·安全·microsoft·edge·社交·动态住宅代理
湫ccc39 分钟前
《Python基础》之pip换国内镜像源
开发语言·python·pip
hakesashou41 分钟前
Python中常用的函数介绍
java·网络·python
菜鸟的人工智能之路1 小时前
极坐标气泡图:医学数据分析的可视化新视角
python·数据分析·健康医疗
菜鸟学Python1 小时前
Python 数据分析核心库大全!
开发语言·python·数据挖掘·数据分析
小白不太白9501 小时前
设计模式之 责任链模式
python·设计模式·责任链模式
喜欢猪猪1 小时前
Django:从入门到精通
后端·python·django
糖豆豆今天也要努力鸭1 小时前
torch.__version__的torch版本和conda list的torch版本不一致
linux·pytorch·python·深度学习·conda·torch
儒道易行1 小时前
【DVWA】RCE远程命令执行实战
网络·安全·网络安全