重合指数求密钥长度

突然发现之前那个求密钥长度的代码具有局限性,所以还是跟着重合指数的方法来写代码吧!(不知道为什么,总想着投机取巧,换到题目就不适用了。淦!)

好了废话不多说。

根据重合指数的方法。首先将明文分组,按列统计其中字符的种类及个数,再计算CI。
在这里插入图片描述
其中 fi 为每列中第 i 种字符的个数, L 为该列的长度。
每列的CI之和取平均值可近似为当前分组长度(即密钥长度)的重合指数,若近似0.068或0.0665(因为按列的话,就变成了单表加密),则很有可能为密钥长度。

很容易写出如下代码(这里考虑的比较简单,代码应该没毛病):

cipher = open(r'ciphertext.txt', 'r').read()
L_cipher = len(cipher)

for n in range(1,38):#枚举密钥长度
    CI = 0#CI为所有列数的重合指数的总和
    for i in range(0,n):#枚举每列的重合指数
        c = ''
        for j in range(i,L_cipher,n):#按列组成字符串
            c += cipher[j]
        L = len(c)
        c_elem = set(c)#取不重复的字符
        CIi = 0 #该列的重合指数
        for litter in c_elem:
            num = c.count(litter)#统计该字符的个数
            CIi += num/L*(num-1)/(L-1)
        CI += CIi
    CI /= n#求每列的平均重合指数
    if 0.06 < CI < 0.07:
        print('密钥长度:',n,'重合指数:',CI)

所以在上一篇文章中的 [De1CTF2019]xorz 的密钥长度可以这样求:

txt = '1e5d4c055104471c6f234f5501555b5a014e5d001c2a54470555064c443e235b4c0e590356542a130a4242335a47551a590a136f1d5d4d440b0956773613180b5f184015210e4f541c075a47064e5f001e2a4f711844430c473e2413011a100556153d1e4f45061441151901470a196f035b0c4443185b322e130806431d5a072a46385901555c5b550a541c1a2600564d5f054c453e32444c0a434d43182a0b1c540a55415a550a5e1b0f613a5c1f10021e56773a5a0206100852063c4a18581a1d15411d17111b052113460850104c472239564c0755015a13271e0a55553b5a47551a54010e2a06130b5506005a393013180c100f52072a4a1b5e1b165d50064e411d0521111f235f114c47362447094f10035c066f19025402191915110b4206182a544702100109133e394505175509671b6f0b01484e06505b061b50034a2911521e44431b5a233f13180b5508131523050154403740415503484f0c2602564d470a18407b775d031110004a54290319544e06505b060b424f092e1a770443101952333213030d554d551b2006064206555d50141c454f0c3d1b5e4d43061e453e39544c17580856581802001102105443101d111a043c03521455074c473f3213000a5b085d113c194f5e08555415180f5f433e270d131d420c1957773f560d11440d40543c060e470b55545b114e470e193c155f4d47110947343f13180c100f565a000403484e184c15050250081f2a54470545104c5536251325435302461a3b4a02484e12545c1b4265070b3b5440055543185b36231301025b084054220f4f42071b1554020f430b196f19564d4002055d79'

cipher = []
for i in range(0,len(txt),2):
    cipher.append(txt[i:i+2])

L_cipher = len(cipher)

for n in range(1,38):#枚举密钥长度
    CI = 0#CI为所有列数的重合指数的总和
    for i in range(0,n):#枚举每列的重合指数
        c = []
        for j in range(i,L_cipher,n):#按列组成字符串
            c.append(cipher[j])
        L = len(c)
        c_elem = set(c)#取不重复的字符
        CIi = 0 #该列的重合指数
        for litter in c_elem:
            num = c.count(litter)#统计该字符的个数
            CIi += num/L*(num-1)/(L-1)
        CI += CIi
    CI /= n#求每列的平均重合指数
    if 0.05 < CI < 0.08:
        print('密钥长度:',n,'重合指数:',CI)

求出

密钥长度: 30 重合指数: 0.0743859649122807

感觉更加简便且通用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值