Hacking

640?wx_fmt=jpeg

凯撒大帝是罗马帝国的奠基人,他是一名杰出的政治家,军事家。不过今天不是讲他的历史故事,而是讲一个算法,叫凯撒密码,凯撒密码的原理很简单:就是通过把字母移动一定的位数来实现加解密。明文中的所有字母从字母表向后(或向前)按照一个固定步长进行偏移后被替换成密文。例如,当步长为3时,A被替换成D,B被替换成E,依此类推,X替换成A。据传凯撒率先在战争中使用这种密码算法,因此这种加密方法被称为凯撒密码。

640?wx_fmt=png

在密码学中,用于解决复杂问题的步骤,称为一种算法,从明文到密文的过程是加密算法,返过来就是解密算法,二者合称为密码算法。  密码算法中需要有密钥, 密钥类似于我们生活中的钥匙,光有锁不行,还必须有钥匙才能打开门, 密码算法+密钥构成了数据加密和解密。

在加密和解密的过程中使用相同密钥的算法称为对称加密,凯撒密码就是典型的对称加密算法,加密和解密使用不同密钥的算法称为公钥加密算法,也称为非对称密码,RSA 就是典型的公钥加密。后者在互联网通信过程起到了非常重要的作用。

现在我们用Python来实现凯撒密码的加解密过程,算法的原理很简单,但如果你还是0岁的算法小白,估计也是一筹莫展。

学过计算机的我们都知道每个字母会对应到一个ASCII码值,比如 A 的ASCII值是65,B是66,Z 是90,小写的 a 对应的是97。

640?wx_fmt=png

ord() 是将字符转换为了对应的 ASCII 值,chr() 将对应的值转换为字符,例如:

>>> ord("A")
65
>>> chr(65)
'A'

如果将A往后移动3位,则可以先将A转换成数值,+3后,再转换回字母,例如:

>>> chr(ord("A")+3)
'D'
>>> chr(ord("B")+3)
'E'
>>> chr(ord("C")+3)
'F'
...
>>> chr(ord("W")+3)
'Z'

以此类推,X 往后移3位之后,值变成了91,对应的字符是“[”,这不是我们所希望的

>>> chr(ord("X")+3)
'['

这时候,有一种叫取模运算的操作,所谓取模运算就是将一个数整除另一个数得到的余数,余数即模运算的值。例如:

>>> 4%8
4
>>> 5%8
5
>>> 8%8
0
>>> 9%8
1

所以,在凯撒密码中,我们需要用到取模运算,以防止移位后超出26个字母的范围,我们知道英文总共有26个字母,X 是第23个(下标从0开始),如果往后移3为就变成26了,超出了字母表的范围,这时候如果 23+3对26取模得到0,刚好是字母表中的第0个字母 A,因此  (X+3)%26=A, (Y+3)%26=B

这里有5个步骤

第一步:计算该字母在字母表中的位置,例如A的位置是0,X的位置就是 ord(“X”)-ord(“A”)=23

>>> ord("X")-ord("A")
23
>>> ord("X")-ord("A") +3
26
>>> (ord("X")-ord("A") +3)%26
0
>>> (ord("X")-ord("A") +3)%26 + ord("A")
65
>>> chr((ord("X")-ord("A") +3)%26 + ord("A"))
'A'

厘清了思路之后,就可以来撸这个算法了,我们只需要把上面的代码封装成函数即可,输入的参数有两个,“X”是要加密的原文,3 是密钥。

def encrypt(char, key=3):
    """
    加密
    """
    return chr((ord(char) - ord("A") + key) % 26 + ord("A"))

def decrypt(char, key=3):
    """
    解密
    """
    return chr((ord(char) - ord("A") - key) % 26 + ord("A"))

测试一下:

plain = "ZENOFPYTHON"
cipher = "".join([encrypt(c) for c in plain])
print(cipher)
>>>CHQRISBWKRQ  # 密文

plain = "".join([decrypt(c) for c in cipher])
print(plain)
>>>ZENOFPYTHON # 明文

问题还没完,如果一段字符串中除了大写字母之外,还有小写,或者还有非字母的情况,我们也要做判断。于是,我们再来改进一下代码,遇到大小写都能处理了

def encrypt(char, key=3):

    if not char.isalpha():
        return char
    else:
        a = "A" if char.isupper() else "a"
        return chr((ord(char) - ord(a) + key) % 26 + ord(a))

def decrypt(char, key=3):
    if not char.isalpha():
        return char
    else:
        a = "A" if char.isupper() else "a"
        return chr((ord(char) - ord(a) - key) % 26 + ord(a))

最后来玩个游戏,我给你一段密文,请将它破解为明文,密文如下:

plain = """Ftq Lqz ar Bkftaz, nk Fuy Bqfqde
Nqmgfurgx ue nqffqd ftmz gsxk.
Qjbxuouf ue nqffqd ftmz uybxuouf.
Euybxq ue nqffqd ftmz oaybxqj.
Oaybxqj ue nqffqd ftmz oaybxuomfqp.
Rxmf ue nqffqd ftmz zqefqp.
Ebmdeq ue nqffqd ftmz pqzeq.
Dqmpmnuxufk oagzfe.
Ebqoumx omeqe mdqz'f ebqoumx qzagst fa ndqmw ftq dgxqe.
Mxftagst bdmofuomxufk nqmfe bgdufk.
Qddade etagxp zqhqd bmee euxqzfxk.
Gzxqee qjbxuoufxk euxqzoqp.
Uz ftq rmoq ar mynusgufk, dqrgeq ftq fqybfmfuaz fa sgqee.
Ftqdq etagxp nq azq-- mzp bdqrqdmnxk azxk azq --anhuage imk fa pa uf.
Mxftagst ftmf imk ymk zaf nq anhuage mf rudef gzxqee kag'dq Pgfot.
Zai ue nqffqd ftmz zqhqd.
Mxftagst zqhqd ue arfqz nqffqd ftmz *dustf* zai.
Ur ftq uybxqyqzfmfuaz ue tmdp fa qjbxmuz, uf'e m nmp upqm.
Ur ftq uybxqyqzfmfuaz ue qmek fa qjbxmuz, uf ymk nq m saap upqm.
Zmyqebmoqe mdq azq tazwuzs sdqmf upqm -- xqf'e pa yadq ar ftaeq!

BkOaz Otuzm Nquvuzs Dqpqqy Oapq ue: ??? 
"""

我准备了奖品,请将明文或密钥值写在留言区。最先回答出来的朋友将得到一份奖品,奖品是价值368元的PyCon北京的门票一张。

PS:北京站本月14号举行,深圳站本月27号举行,报名地址戳阅读原文。本游戏解释权归我所有

640?

推荐阅读

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值