祕鑰爆破 變種維吉尼亞
阿新 • • 發佈:2019-01-13
加密程式碼如下
from random import randrange
text_list=' !"#$%&\'()*+,-./0123456789:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\t\n'
key=[randrange(1,97) for i in range(randrange(15,30))]
print('key = '+str(key))
def encrypt(s,k):
out=''
for i in range(len(s)):
index= text_list.index(s[i])
index*=k[i%len(k)]
index%=97
out+=text_list[index]
return out
plain=open('plain.txt','r').read() # TOEFL reading passage
cipher=encrypt(plain,key)
open('cipher.txt','w').write(cipher)
可以發現 對每個單詞做了一下對映
我們需要知道祕鑰的長度 解密的祕鑰 手上只有密文 看起來不可讀 怎麼分析?
- 首先最關鍵的是要發現空格不會變 這樣就可以猜測單詞長度了
- 間隔重複祕鑰 按照長度找 比如每三個長度取出來一串 最後計數 發現{gY出現的最多 猜測是the 得到祕鑰對應位置的值 (解密祕鑰和加密祕鑰不同,長度一致)
- 找key長度 對每個{yG找到在ciphertext中的位置
[3, 61, 612, 1105, 1279, 1656, 2091]
考慮到第一個{yG出現在第一個key長度中
那麼對每個數-3
得到
[0, 58, 609, 1102, 1276, 1653, 2088]
發現他們有個共同的倍數29
linux下可以輸入命令 factor 58 以此類推 或者手動gcd搞
所以keylen=29
還有一個關鍵是第一個單詞長度為2
所以可能為
In
By
At
As
如何確定
每29個算一下看出來的結果 ※※※※※
不是a-zA-Z0-9,.:-
上面這個解密可以自己實現一下
就是個逆元
ab mod 97=c mod 97
已知a,c求b
b = c (a在97意義下的逆元) %97
哦對了
當你找出來較多的單詞 就可以百度啦! - 題目做完發現可以用 ※※※※※處的方法來暴力破解= = 問題不大…
混亂的解密指令碼
import gmpy2
import sys
from random import randrange
import re
from collections import Counter
text_list=' !"#$%&\'()*+,-./0123456789:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\t\n'
cipherText = open('cipher.txt','r').read()
print sys.argv[1]
def inv(x):
return gmpy2.invert(x,97)
def repeat():
c = Counter()
for i in range(len(cipherText)):
s = cipherText[i:i+int(sys.argv[1])]
c[s] = c[s] + 1
print sorted(c.items(),key = lambda eachItem:eachItem[1],reverse=True)
def brute():
for keylen in range(15,30):
num = 0
if len(cipherText)%keylen==0:
num = len(cipherText)/keylen
else:
num = len(cipherText)/keylen+1
L = []
for i in range(num):
start = i*keylen
end = (i+1)*keylen
s = cipherText[start:end]
L.append(s)
for start in range(keylen):
for length in range(1,keylen-start):
if length ==3 :
c = Counter()
ans = []
for mylist in L:
ans.append(mylist[start:start+length])
Max = 0
poss = ''
for a in ans:
c[a] = c[a] + 1
if c[a] > Max:
Max = c[a]
poss = a
print "_______________"
# print (keylen,start,length,sorted(c.items(),key = lambda eachItem:eachItem[1],reverse=True))
print (keylen,start,length,poss,Max)
def findonekey(s,to):
indexto=text_list.index(to)
indexs=text_list.index(s)
return inv(indexs)*indexto%97
def splitInto():
cnt = 0
fuckthistext = open('this_is_21.txt','r').read()
for i in range(len(fuckthistext)):
if i%29==0:
print "012345678901234567890123456789here is the line {0}".format(cnt)
print fuckthistext[i:i+29]
cnt += 1
splitInto()