import re
import sys
in_text=sys.argv[1:]
P_E_S=['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
R_A=['q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m']
def encryption(plaintex):
ciphertext=[]
for i in plaintex:
ciphertext.append(R_A[P_E_S.index(i)])
return ciphertext
def decryption(ciphertext):
plaintext=[]
for i in ciphertext:
plaintext.append(P_E_S[R_A.index(i)])
return plaintext
def SingleSableSub(in_text):
print("此加密解密只涉及26个英文字母")
print('---------------------------------')
choice=input("1. 加密 2. 解密 3. 分析 ")
in_text=''.join(in_text)
in_text=re.compile('[^a-zA-Z]').sub('', in_text.lower())
if choice is '1':
print('加密结果: '+''.join(encryption(in_text)))
elif choice is '2':
print("解密结果: "+''.join(decryption(in_text)))
elif choice is '3':
print("分析结果:")
print(analysis(in_text))
else:
print("输入错误")
def analysis(ciphertext):
result={}
sum=0
for i in ciphertext:
result[i]=ciphertext.count(i)
for value in result.values():
sum+=int(value)
for key,value in result.items():
result[key]=float(value)/sum
return result
if __name__ == '__main__':
try:
SingleSableSub(in_text)
except EOFError:
exit()
从这个图表中不难看出t的贡献率高达0.15,那我们可以大胆推测,t就是e的变换;再看其他的,会发现,o f的 贡献也很高。那可能是 t r a i n o的替换,那我们不妨来尝试一下。先把t换掉,然后再找出 o f的位置,可以看到of常常组合在一起,那可能的组合就有 tr ra ai in io 然后带进去看一看哪些比较合理,这里我们看到了一个组合ttf 也就是 ee_ 这里我们想一下常常和ee搭配的组合(当然是在第二步的基础上eer eea eei een eeo)可以发现een可能比较常见,那我们断定o 是 i 的变换 , f 是 n 的变换。填进去。也只能推出这么多了,因为我们选的样本太少了,不过可以看出,如果我进行大篇幅的加密,那么自然语言的特点就会越来越突出。
明文:i m g r o w i n g l i k e a s e e d r a i n s b e e n f a l l i n g o n m e
密文:o d u k g v ofu s o a t q l t t r k q of l w t t f y q s s of u g f d t
推测:i i n i e ee i n een i n e
拓展:可见如果这样加密,具有明显的统计学特征,那我们是不是可以变种方法。
1. 同音词替代,这是一种一对多的替代:举个例 e可以替换成为 a c d f 中的随机一个,这种方法大大增加了单个字符的使用频率分析难度,但是值得一提的是,它并没有改变自然语言结构,也就是说一些双音节组合,或者多音节组合的规律特征仍然存在。所以依然可以分析。
若p1 p2在同一列,对应密文c1 c2分别是紧靠p1 p2 下方的字母。其中第一行被看做是最后一行的下方。如,按照前表,wp 对应 fu
若p1 p2不在同一行,不在同一列,则c1 c2是由p1 p2确定的矩形的其他两角的字母(至于横向替换还是纵向替换要事先约好,或自行尝试)(这里取该字母所在行为密文所在行)。如,按照前表,wr 对应 bp
那么我又又又写了个代码。。。
import re
import sys
in_text=sys.argv[1:]
P_E_S=['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
def encryption(plaintext,matrix):
ciphertext=[]
for i in plaintext:
if i[0] != 'j':
ind_col_1=location(i[0],matrix)
else:
ind_col_1=location('i',matrix)
if i[1] != 'j':
ind_col_2=location(i[1],matrix)
else:
ind_col_2=location('i',matrix)
if ind_col_1[0]==ind_col_2[0]:
ciphertext.append(matrix[ind_col_1[0]][(ind_col_1[1]+1)%5])
ciphertext.append(matrix[ind_col_2[0]][(ind_col_2[1]+1)%5])
elif ind_col_1[1]==ind_col_2[1]:
ciphertext.append(matrix[(ind_col_1[0]+1)%5][ind_col_1[1]])
ciphertext.append(matrix[(ind_col_2[0]+1)%5][ind_col_2[1]])
else:
ciphertext.append(matrix[ind_col_1[0]][ind_col_2[1]])
ciphertext.append(matrix[ind_col_2[0]][ind_col_1[1]])
return ciphertext
def decryption(ciphertext,matrix):
plaintext=[]
for i in ciphertext:
if i[0] != 'j':
ind_col_1=location(i[0],matrix)
else:
ind_col_1=location('i',matrix)
if i[1] != 'j':
ind_col_2=location(i[1],matrix)
else:
ind_col_2=location('i',matrix)
if ind_col_1[0]==ind_col_2[0]:
plaintext.append(matrix[ind_col_1[0]][(ind_col_1[1]+4)%5])
plaintext.append(matrix[ind_col_2[0]][(ind_col_2[1]+4)%5])
elif ind_col_1[1]==ind_col_2[1]:
plaintext.append(matrix[(ind_col_1[0]+4)%5][ind_col_1[1]])
plaintext.append(matrix[(ind_col_2[0]+4)%5][ind_col_2[1]])
else:
plaintext.append(matrix[ind_col_1[0]][ind_col_2[1]])
plaintext.append(matrix[ind_col_2[0]][ind_col_1[1]])
i=0
while i < len(plaintext)-1:
if plaintext[i]=='x':
if plaintext[i-1]==plaintext[i+1]:
plaintext.pop(i)
else:
i+=1
return plaintext
def playfair(in_text):
print("此加密解密只涉及26个英文字母")
print('---------------------------------')
choice=input("1. 加密 2. 解密 ")
key=input('密钥: ')
in_text=''.join(in_text)
in_text=re.compile('[^a-zA-Z]').sub('', in_text.lower())
sublist=DataPre(in_text)
AlphSubTable=ASTgenerator(key)
if choice is '1':
print('加密结果: '+''.join(encryption(sublist,AlphSubTable)))
elif choice is '2':
print("解密结果: "+''.join(decryption(sublist,AlphSubTable)))
else:
print("输入错误")
def DataPre(data):
i=0
sublist=[]
while i < len(data):
try:
if data[i] != data[i+1]:
sublist.append(data[i]+data[i+1])
i=i+2
else:
sublist.append(data[i]+'x')
i=i+1
except:
data=data+'x'
return sublist
def ASTgenerator(key):
mainkeys=[]
for i in key:
if i not in mainkeys:
mainkeys.append(i)
output=[]
P_E_S_I=P_E_S
for ind in range(5):
line=[]
col=0
while col < 5:
if len(mainkeys) != 0:
pop_letter=P_E_S_I.pop(P_E_S_I.index(mainkeys.pop(0)))
if pop_letter =='j':
continue
else:
line.append(pop_letter)
col+=1
elif len(P_E_S_I) != 0:
pop_letter=P_E_S_I.pop(0)
if pop_letter =='j':
continue
else:
line.append(pop_letter)
col+=1
output.append(line)
return output
def location(letter,martix):
for ind in range(5):
for col in range(5):
if martix[ind][col]==letter:
return [int(ind),int(col)]
if __name__ == '__main__':
try:
playfair(in_text)
except EOFError:
exit()