秘钥爆破 变种维吉尼亚

加密代码如下

from random import randrange
text_list=' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`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:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`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()
    原文作者:维吉尼亚加密问题
    原文地址: https://blog.csdn.net/qq_38677814/article/details/85243737
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞