python - 为什么我在 Python3 中的巧合指数之和的平均值是错误的?
问题描述
我编写了一个程序来尝试通过计算每个 x 元素切割的文本的所有重合索引的平均值来查找x
法语vigenere 密文中的密钥长度(应该是随机字符串),基本上我是试图根据这个参考网站获得最接近 0.06/0.07 的 IC平均值,但我的平均值看起来不对。
注意:我只使用大写字符串,根本没有标点符号,没有特殊字符,也没有空格。
我有 3 个函数,一个函数给我一个文本中出现字母的列表。
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def freq(txt):
"""
give back all occurences of letters in a list
"""
hist = [0.0] * len(alphabet)
for letter in txt:
hist[alphabet.index(letter)] += 1
return hist
def IC(occurences):
"""
this function takes a list of occurences of letters from a text and calculates the IC
and returns the IC
"""
sum_ = 0
n = sum(occurences)
if n == 1:
return 0
for occ_letter in occurences:
sum_ += occ_letter * (occ_letter - 1)
sum_ /= n * (n - 1)
return sum_
# These two functions work well (or so I believe), but when I wrote this one :
# This function could be wrong
def key_length(cipher):
"""
cipher is the ciphered text.
Find the length of the key by cutting the text and trying to find a mean value over 0.06
Returns the length of the key
"""
max_key_len = 20 # (the length of the key will never be over 20)
max_ = 0
index_max = 0
for x in range(1, max_key_len + 1): # Going from 1 to 20
pieces = [cipher[i : i + x] for i in range(0, len(cipher), x)]
# calculating the mean value of all the piece in text cut in x pieces
mean_IC = sum(IC(freq(piece)) for piece in pieces) / len(pieces)
print(mean_IC, x)
if mean_IC > max_:
max_ = mean_IC
index_max = x
if mean_IC > 0.06:
break
return index_max
跟踪 IC 的平均值在此示例文本中为我提供了以下信息:
0.043117408906882586 20
0.03727725599070627 19
0.03944106378183457 18
0.04047088532382649 17
0.04331597222222223 16
0.04154995331465919 15
0.037422037422037424 14
0.04287251210328133 13
0.037350246652572215 12
0.03882301273605619 11
0.04291938997821349 10
0.04191033138401558 9
0.04185267857142856 8
0.03522504892367906 7
0.03686274509803924 6
0.04554455445544554 5
0.04199475065616799 4
0.043392504930966455 3
0.03557312252964427 2
0.0 1
这些值都没有超过 0.06(但有些应该是因为 7 是真正的密钥长度)。我在网上查看了一个完全执行此操作的密码学网站(单击按钮CALCULATE PROBABLE KEY-LENGTHS
),我得到了一些与 L 是密钥长度相同的文本真正不同的东西,总之有问题,但我似乎不能找到它:
L=7 IC ≈ 0.07832 ± 0.006 --> This is the key
L=14 IC ≈ 0.07986 ± 0.013
L=21 IC ≈ 0.07504 ± 0.015
L=5 IC ≈ 0.04717 ± 0.028
L=10 IC ≈ 0.04667 ± 0.028
L=15 IC ≈ 0.04646 ± 0.029
L=19 IC ≈ 0.04616 ± 0.029
L=20 IC ≈ 0.04562 ± 0.029
L=22 IC ≈ 0.04523 ± 0.03
L=11 IC ≈ 0.04516 ± 0.03
L=4 IC ≈ 0.04515 ± 0.03
L=3 IC ≈ 0.04494 ± 0.03
L=1 IC ≈ 0.04487 ± 0.03
L=17 IC ≈ 0.04462 ± 0.03
L=2 IC ≈ 0.04453 ± 0.03
L=9 IC ≈ 0.04373 ± 0.031
L=23 IC ≈ 0.04352 ± 0.031
L=13 IC ≈ 0.04336 ± 0.032
L=8 IC ≈ 0.04319 ± 0.032
L=6 IC ≈ 0.04278 ± 0.032
L=26 IC ≈ 0.0426 ± 0.032
L=12 IC ≈ 0.04199 ± 0.033
L=16 IC ≈ 0.04128 ± 0.034
L=25 IC ≈ 0.04131 ± 0.034
L=18 IC ≈ 0.04006 ± 0.035
L=24 IC ≈ 0.03681 ± 0.038
解决方案
在密钥长度猜测中,您不使用 计算片段pieces[i:i+x]
,这不会提供执行 IC 评估所需的正确陪集。
相反,您可能想要定义切入列函数:
def cut_in_columns(text, k):
"""
Cut text in k columns
"""
columns = [[] for _ in range(k)]
for i, l in enumerate(text):
columns[i % k].append(l)
return columns
这将为您提供权利pieces
。由于这是真的,我可能会将您重定向到这篇文章:https ://pages.mtu.edu/~shene/NSF-4/Tutorial/VIG/Vig-IOC-Len.html关于密钥长度猜测。
在您的代码中替换它会产生所需的结果。
基本属性在于这些密码方法的定义。
顺便说一句,您应该测试您发布的代码,您有一个未定义的变量(法语moyenne
混合mean
)并且在您的最大计算中提前返回,这甚至不是最大计算......您应该确保您的最小工作示例确实有效。
推荐阅读
- java - .jdbc4.MySQLIntegrityConstraintViolationException:Spring JPA 中针对@Column 的重复条目(unique = true)
- django - Django dumpdata CommandError:无法序列化数据库:int() 的无效文字,基数为 10
- javascript - java脚本下拉控件(多选)上的可访问性(ADA)编码挑战
- javascript - 表达式如何在来自 sessionStorage 的错误条件下计算为真?
- node.js - 如何在函数内部使用 Visual Studio Code 调试 Node.js?
- python - 人名的python正则表达式
- c - 为什么这段代码运行仍然有效,有 '&' 或没有 '&'?
- vba - MS-Access 模态表单而不是消息框
- pandas - 如何在多个列上透视表和聚合?
- python - 如何在多个 Celery 任务中结合实施 Prometheus 监控?