仿射密码的加密算法是一个线性变换,即对任意的明文字符x,先找到x对应的数字(a-z分别对应0-25),然后进行加密变换: y = e ( x ) = a ∗ x + b ( m o d 26 ) y = e(x) = a*x+b(mod 26) y=e(x)=a∗x+b(mod26),找出数字y对应的字母x*,x*就是x的密文。
在知道a和b的前提下解密过程就是: x = d ( e ( x ) ) = a ′ ( e ( x ) − b ) ( m o d 26 ) x=d(e(x))=a'(e(x)-b)(mod 26) x=d(e(x))=a′(e(x)−b)(mod26),其中 a ′ a' a′为a的逆元( a ∗ a ′ = 1 ( m o d 26 a*a'=1(mod 26 a∗a′=1(mod26)。
下面我们以 e ( x ) = ( 5 x + 8 ) m o d 26 e(x)=(5x+8)mod26 e(x)=(5x+8)mod26函数为例子进行介绍,要加密的字符串为 AFFINE CIPHER。
其对应的加密结果是 IHHWVCSWFRCP。
对于解密过程,正常解密者具有a与b,可以计算得到 a ′ a' a′为 21,所以其解密函数是d(x)=21(x−8)(mod26),解密如下:
'''
加密算法
'''
def Reflect():
d = {
}
j = 0
for i in range(ord('a'), ord('z') + 1):
d[chr(i)] = j
j += 1
return d
def Encode(a, b, s, d):
c = ''
for i in s:
if i == ' ':
c += i
continue
f = (a * d[i] + b) % 26
for key, value in d.items():
if value == f:
c += key
break
return c
s = input('请输入要加密的字符串:')
s = s.lower()
print('-----------加密方程为a*x + b(mod 26)--------------')
a = eval(input('请输入参数a:'))
b = eval(input('请输入参数b:'))
d = Reflect()
c = Encode(a, b, s, d)
print('密文为:',c)
采用频率分析法,根据大量英文文献的统计得出,出现最多次数的两个英文字母为E和T,我们可以先统计出密文中个字母出现的次数,然后将出现最多的字母p1看做是由’E’加密而来的,将出现第二多p2的字母看做是由’T’加密而来的,令 e ( x ) = a ∗ x + b ( m o d 26 ) e(x)=a*x+b(mod 26) e(x)=a∗x+b(mod26),因为E对应4,T对应19,有 { 4 a + b = p 1 ( m o d 26 ) 19 a + b = p 2 ( m o d 26 ) \begin{cases} 4a+b=p1(mod 26) \\ 19a+b=p2(mod 26)\end{cases} { 4a+b=p1(mod26)19a+b=p2(mod26)
可以解出a与b的值,从而计算出明文值。若破译出的明文语义有误,则将’T’对应出现第三多的字母,重新计算a和b,依此类推,直到语义无误。
解密代码:
'''
唯密文攻击
'''
#频率分布列表
index = ['e', 't', 'a', 'o', 'i', 'n', 's', 'h', 'r', 'd', 'l', 'c', 'u', 'm', 'w', 'f', 'g', 'y', 'p', 'b', 'v', 'k', 'j', 'q', 'x', 'z']
def frequency_Sort(s):
d = dict()
for i in range(ord('a'),ord('z')+1):
sum = 0
for j in s:
if ord(j)==i :
sum += 1
d[chr(i)] = sum
d = sorted(d.items(), key = lambda x: x[1], reverse = True) #d的类型变为list,不再是dict
c = []
for k in d:
c.append(k[0])
return c
def coefficient(a, b, m, n): #求系数
x1 = d[a]
x2 = d[b]
y1 = d[m]
y2 = d[n]
k = 0
f = (x2 - x1)%26
point = (y2 - y1) % 26
while f % point != 0:
f += 26
k += 1
if k == 1000:
break
if k == 1000:
return 2,0
_a = ( f / point ) % 26
_b = ( x1 - y1 * _a) % 26
return _a , _b
def decodeFunction(a, b):
q = []
t = [0,1]
numChu = 26 // a
numYu = 26 % a
while numYu != 0:
q.append(numChu)
j = a
a = numYu
numChu = j // a
numYu = j % a
q.append(numChu)
for i in range(0,len(q) - 1):
f = -q[i] * t[i + 1] + t[i]
t.append(f)
a = t[-1] % 26
b = (-b * t[-1]) % 26
return a, b
s = input('请输入密文:')
s = s.lower()
j = 0
d = dict()
for i in range(ord('a'), ord('z') + 1):
d[chr(i)] = j
j += 1
w = frequency_Sort(s)
bug = ''
for two in range(0, 25):
for p1 in range(0, len(w) - 1):
for p2 in range(p1 + 1, len(w)):
a, b = coefficient(w[p1], w[p2], index[two], index[two + 1])
if a % 2 == 0 or a % 13 == 0:
continue
a, b = decodeFunction(a, b)
c = ''
for i in s:
if i == ' ':
c += i
continue
f = (d[i]*a + b)%26
for q,v in d.items():
if v == f:
c += q
break
print('明文为:{}'.format(c))
bug = input("若语义有误则输入'c'继续尝试(输入's'退出):")
if bug == 's':
break
else:
continue
if bug == 's':
break
if bug == 's':
break