0.前言
最开始只是想整理一下密码学课程的作业,后面越写越多,就索性写成一篇入门的介绍。我会把自己对对称加密的理解和一些作业的代码串起来,力图清晰明白地展示出来,文中所有代码都放在我的Github上,如果有错误之处还请轻拍。
1.对称密码基础
加密是为了防止要传达的内容被别人知道。例如,你如果想在课堂上传小纸条給后位小红说:i love coding
,但又怕在递纸条的过程中被老师看到,知道了你的心思,于是将每个字母变字母表中的后一个字母(如a变成b,i变成j,z变成a),得到密文:j mpwf dpejoh
,这样即老师人拿到这纸条,也不知道你说的是什么。
这就是一个加密的过程,把原本的内容称为明文,一般用p表示;加密后得到的内容称为密文,一般用c表示;而加密的这个过程可以看做是一个加密函数E,即
$$c = E( p )$$
E是指Encrypt,函数输入是明文,输出是加密之后的密文。上面的例子中i love coding
便是明文,j mpwf dpejoh
便是密文,而把字母在字母表中向后移动一位的操作就是加密函数。
在小红得到小纸条后,可以根据你加密的方法,将每个字母变成字母表中的前一个字母,就可以从你的密文小纸条得到你要说的内容i love coding
,心领神会,顺便还会怀疑一下你的脑袋……无论怎样,这个解密的过程就也可以看做是一个解密函数D,即
$$p = D( c )$$
D是指Decrypt,函数输入是密文,输出是解密之后的明文。
在这个过程这种,小红能够成功解密小纸条的前提是,你得和她在课前约定好你加密的时候移动的是1位,2位还是几位,不然他就会和老师一样一脸懵逼,不知道你在说啥。你们提前约定好的这个“几位”,就是加密和解密的密钥k,你会根据这个秘钥来进行加密,小红会根据这个秘钥来进行解密。
所以你的传纸条的动作抽象成这个过程:
明文p---->加密函数E---->密文c---->传输---->密文c----->解密函数D---->明文p
或者用公式来表达是:
$$c = D_k( E_k( c ) )$$
用大白话说就是:明文用同一个密钥先加密再解密得到的还是同一个明文(等于没说...)
从这里我们可以总结出加密体质的五个要素:{明文p,密文c,密钥k,加密函数E,解密函数D},对称解密的的意思就是说,加密和解密的密钥是一样的,上面的过程是不是正好很对称呢?
为了方便使用,不用每次自己手动掰手指数字符,你还写了Python程序:
# 移位密码
def _move_leter(letter, n):
"""
把字母变为字母表后n位的字母,z后面接a
:param letter: 小写字母
:param n: 要移动的字母
:return: 移动的结果
"""
return chr((ord(letter) - ord('a') + n) % 26 + ord('a'))
def Encrypt(k, p):
"""
移位密码加密函数E
:param k: 秘钥k,每个字母在字母表中移动k位
:param p: 明文p
:return: 密文c
"""
letter_list = list(p.lower())
c = ''.join([_move_leter(x, k) for x in letter_list])
return c
def Decrypt(k, c):
"""
移位密码解密函数D
:param k: 秘钥k,每个字母在字母表中移动k位
:param c: 密文c
:return: 明文p
"""
letter_list = list(c.lower())
p = ''.join([_move_leter(x, -k) for x in letter_list])
return p
if __name__ == '__main__':
p = 'ilovecoding'
print('明文:' + p)
print('密文:' + Encrypt(1, p))
print('解密:' + Decrypt(1, Encrypt(1, p)))
assert Decrypt(1, Encrypt(1, p)) == p
运行这段代码,就可以看到输出了:
明文:ilovecoding
密文:jmpwfdpejoh
解密:ilovecodin