维吉尼亚(Vigenere)密码----分析、破解

维吉尼亚密码是一种多表替换密码。这种替换法是循环使用有限个字母来实现替换的一种方法。这种加密的加密表是以字母表移位为基础把26个英文字母进行循环移位,排列在一起,形成26*26的方正。采用的算法为:
f(pi)=(pi+ki)mod 26
在这里插入图片描述

0x01 加密过程

以密钥字母选择行,以明文选择列,两者的交点就是加密生成的密文

加密双方必须同时握有上表所示的表格,另外还必须商议出一把共同秘钥,这里必须强调的是表并非秘钥的一部分,也就是说,即使表被公开,也不影响系统的安全性

比如说:使用秘钥CRYPTOGRAPHY对明文STRIKE WHILE THE IRON IS HOT加密

  • 将秘钥重复地写在明文的上方
    CR YP TO GR AP HY CR YP TO GR AP H
    ST RI KE WH IL ET HE IR ON IS HO T

  • 上下两个字母去查表
    比如第一个字母对为(C,S),查表为U,依次查询下去

  • 得到结果

UKPXDSCYIAIRJVGGHBOJHDA

0x02 解密过程

以秘钥字母选择行,从中找到密文字母,密文字母所在列的列名就是明文字母

  • 将秘钥重复地写在明文的上方
  • 根据秘钥所在的行,找到密文,取列名
0x03数学描述

设密钥K=(k1,k2,…,kd),明文M=(m1,m2,…,mn),密文C=(c1,c2,…,cn);

加密变换为:ci=Eki(mi)=mi+ki(mod 26)

解密变换为:mi=Dki(ci)=ci-ki(mod 26)

通常通过查询维吉尼亚表进行加解密。

0x04 加密算法
"""
实现维吉尼亚的加密解密
"""

def VigenereEncode(message,key):
    pLen=len(message)
    kLen=len(key)
    message=message.upper()
    key=key.upper()
    raw = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"  # 明文空间
    out=""
    for i in range(0,pLen):
        j=i%kLen
        if message[i] not in raw:
            out+=message[i]
            continue
        encodechr=chr((ord(message[i])-ord('A')+ord(key[j])-ord('A'))%26+ord('A'))
        out+=encodechr
    return out


if __name__ == "__main__":
    P="strikewhiletheironishot"
    key="cryptography"
    out=VigenereEncode(P,key)
    print("加密后的密文是:")
    print(out)

在这里插入图片描述

0x05 解密算法
"""
实现维吉尼亚的加密解密
"""

def VigenereEncode(message,key):
    pLen=len(message)
    kLen=len(key)
    message=message.upper()
    key=key.upper()
    raw = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"  # 明文空间
    out=""
    for i in range(0,pLen):
        j=i%kLen
        if message[i] not in raw:
            out+=message[i]
            continue
        encodechr=chr((ord(message[i])-ord('A')+ord(key[j])-ord('A'))%26+ord('A'))
        out+=encodechr
    return out

def VigenereDecode(message,key):
    """
    解密
    :param message: 密文
    :param key: 密钥
    :return: 明文
    """
    CLen=len(message)
    kLen=len(key)
    key=key.upper()
    raw = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"  # 密文空间
    plaintext=""
    for i in range(0,CLen):
        j=i%kLen
        if message[i] not in raw:
            plaintext+=message[i]
            continue
        decodechr=chr((ord(message[i])-ord('A')-ord(key[j])-ord('A'))%26+ord('A'))
        plaintext+=decodechr
    return plaintext


if __name__ == "__main__":
    P="strikewhiletheironishot"
    key="cryptography"
    encode=VigenereEncode(P,key)
    decode=VigenereDecode(encode,key)
    #print("加密后的密文是:")
    print(decode)

在这里插入图片描述

0x06 维吉尼亚分析目标

  • 加密:ek(x1,x2,…,xm)=(x1+k1,x2+k2,…,xm+km)
  • 解密:dk(y1,y2,…,ym)=(y1-k1,y2-k2,…,ym-km)
  • 秘钥:k=(k1,k2,km),所有的运算都是在模26下进行的
  • x,y是26个字母下标,a=0,b=1,…,z=25

我们分析一个维吉尼亚密码的目标是求出k1,k2,km,方法有:

  • Kasiski method(1863,Friedrich kasiski)
  • 重合指数法(1920,William Friedman)

kasiski测试法:
寻找密文中相同的片段对,计算每对相同片段对之间的距离,不妨记为d1,d2,…,di,若令秘钥字的长度为m,则m=gcd(d1,d2,…,di),gcd是求d1,d2,…,di的最大公约数。
若两个相同的明文片段之间的距离是秘钥片段的倍数,则这两个明文片段对应的密文一定相同。

若密文中出现两个相同的秘文段(密文段的长度m>2),则它们对应的明文将以很大的概率相同(99%)

我们用CAP分析一个例子:
已知一个密文:zicvtwqngrzgvtwavzhcqyglmgj
测试过程

  • 1、在密文中找到重复的字符串:vtm
  • 2、两个字符串的起始位置分别为4和13
  • 3、其距离为9
  • 4、9的因数有3和9
  • 5、根据步骤4的因数,秘钥的长度可能为3或9

在这里插入图片描述
所以接下来我们要判断密钥的长度到底为多少,当我们面对一篇密文时,若要分辨其为单表代换法还是多表代换法,可用重合指数。
设X=x1x2…xn是一个长度为n的英文字母串,则x中任意选取两个字母相同的概率定义为重合指数,用Ic(x)
在这里插入图片描述
当n趁近为无穷大时
在这里插入图片描述

  • IC为重合指数
  • 单表替换加密的密文IC=0.065
  • 多表替换加密IC=0.038
    我们来举个例子来计算IC:
    密文:HLUBNWFSFKIGIHMGBSIMMBSEJMAFUTQECIILJSUBBAXMAJCWXCMBSGZGGSMKBHUQBETVUSMLMERCFDTWUBASWERFIELOMVYSIMMYYEDDMMSGZANCOFYYTIHLJRYOHKLOFHIEFKQOFAAIZGIEJHAKNZJSQRUQXDKWHSNNFAOUMOROFAAIZPIQYHQFYSWEFKILDPQGIXUEADFWNNFVYOTRXRGQKRUSHVYHAGYONTTZISIEPUOFXAZRNZTSQKBGIISMIMIISMIMXHAHUFZNMFGWIMMBQWQLTSMZTUXRBSAEMFGWIHUAMWQFFVCKNSMTIJYYRCOJRASBOEYHQAIKYPAKYJKUXVUFIGGBCFYHQKIJQDFVULBOGZXTQOIMIMWHQOXUQEMBIXKYAIBSAEFCUKPYAILKJLRRIQTURSYDQUOYSOJLXRIQTUBIHC
    我们用CAP分析,就不手算了,计算量太大
    我们将密文粘贴到Ciphertext,在basic tools有个IC点击
    在这里插入图片描述
    点击run,出来0.04319,和0.038很近,猜测为多表代换
    在这里插入图片描述
    重合指数确定秘钥长度
    根据Kasiski测试方法得到的m,可以将密文按照下列形式排列
    在这里插入图片描述
    每一行都是单表代换,若m确实是秘钥的长度,则上述矩阵中的每一行都是由同一个密钥ki加密得到,这说明每一行即是一个单表代替,这时计算每一行的重合指数,应该更接近0.065;
    若m不是密钥的长度,则上述矩阵中的每一行不是由同一个密钥ki加密得到,这说明每一行是一个等概随机的字母串(对密文的要求),这时计算每一行的重合指数,应该更接近0.038。
    密文:
    CHREEVOAHMAERATBIAXXWTNXBEEOPHBSBQMQEQERBWRVXUOAKXAOSXXWEAHBWGJMMQMNKGRFVGXWTRZXWIAKLXFPSKAUTEMNDCMGTSXMXBTUIADNGMGPSRELXNJELXVRVPRTULHDNQWTWDTYGBPHXTFALJHASVBFXNGLLCHRZBWELEKMSJIKNBHWRJGNMGJSGLXFEYPHAGNRBIEQJTAMRVLCRREMNDGLXRRIMGNSNRWCHRQHAEYEVTAQEBBIPEEWEVKAKOEWADREMXMTBHHCHRTKDNVRZCHRCLQOHPWQAIIWXNRMGWOIIFKEE
    CAP分析Kasiski:
    在这里插入图片描述
    因数出现最多次数是5,即密码长度最有可能为5,需要进一步确定
    接下来我们计算IC,将密文排列
    在这里插入图片描述
    计算每一行的IC,都接近0.065,因此可以推断,密钥的长度m=5

在这里插入图片描述
接下来就是确定密钥了。
思路

  • 利用频率分析方法分析,对上面排成的矩阵,每一行都是循环移位密码,参考凯撒密码的分析方法。单表替换不改变字母的统计规律
发布了168 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41683305/article/details/104626649