1. 程式人生 > >祕鑰爆破 變種維吉尼亞

祕鑰爆破 變種維吉尼亞

加密程式碼如下

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)

可以發現 對每個單詞做了一下對映
我們需要知道祕鑰的長度 解密的祕鑰 手上只有密文 看起來不可讀 怎麼分析?

  1. 首先最關鍵的是要發現空格不會變 這樣就可以猜測單詞長度了
  2. 間隔重複祕鑰 按照長度找 比如每三個長度取出來一串 最後計數 發現{gY出現的最多 猜測是the 得到祕鑰對應位置的值 (解密祕鑰和加密祕鑰不同,長度一致)
  3. 找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
    哦對了
    當你找出來較多的單詞 就可以百度啦!
  4. 題目做完發現可以用 ※※※※※處的方法來暴力破解= = 問題不大…

混亂的解密指令碼

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()