破解维吉尼亚密码:频率分析与攻击方法
1. 频率分析基础
1.1 生成字母频率排序字符串
在进行频率分析时,我们需要将字母按照其在文本中出现的频率进行排序。以下是实现这一功能的代码示例:
# 假设 freqPairs 是一个包含频率计数和对应字母的元组列表
freqOrder = []
for freqPair in freqPairs:
freqOrder.append(freqPair[1])
return ''.join(freqOrder)
通过上述代码,我们可以得到一个字母按频率排序的字符串。例如,对于特定的文本,可能会得到像
'ETIANORSHCLMDGFUPBWYVKXQJZ'
这样的结果,其中
E
是最常见的字母,
T
是第二常见的,依此类推。
1.2 计算频率匹配得分
为了评估一段文本的字母频率与正常英语文本的匹配程度,我们可以使用
englishFreqMatchScore()
函数。以下是该函数的实现:
def englishFreqMatchScore(message):
freqOrder = getFrequencyOrder(message)
matchScore = 0
# 统计前六个最常见字母的匹配数
for commonLetter in 'ETAOIN'[:6]:
if commonLetter in freqOrder[:6]:
matchScore += 1
# 统计后六个最不常见字母的匹配数
for uncommonLetter in 'ETAOIN'[-6:]:
if uncommonLetter in freqOrder[-6:]:
matchScore += 1
return matchScore
该函数返回一个介于 0 到 12 之间的整数,得分越高表示文本的字母频率与正常英语文本越匹配。
1.3 频率分析总结
通过频率分析,我们可以了解文本中字母的分布情况,并与正常英语文本的频率进行比较。这有助于我们判断一段文本是否可能是英语,或者是否经过了加密。在后续的维吉尼亚密码破解中,频率分析将发挥重要作用。
2. 破解维吉尼亚密码的方法
2.1 字典攻击
2.1.1 原理
字典攻击是一种简单直接的破解方法,它尝试使用字典文件中的每个单词作为维吉尼亚密码的密钥进行解密。如果密钥是一个英语单词,这种方法通常可以快速找到正确的解密结果。
2.1.2 代码实现
以下是使用字典攻击破解维吉尼亚密码的 Python 代码:
import detectEnglish, vigenereCipher, pyperclip
def main():
ciphertext = """Tzx isnz eccjxkg nfq lol mys bbqq I lxcz."""
hackedMessage = hackVigenereDictionary(ciphertext)
if hackedMessage != None:
print('Copying hacked message to clipboard:')
print(hackedMessage)
pyperclip.copy(hackedMessage)
else:
print('Failed to hack encryption.')
def hackVigenereDictionary(ciphertext):
fo = open('dictionary.txt')
words = fo.readlines()
fo.close()
for word in words:
word = word.strip()
decryptedText = vigenereCipher.decryptMessage(word, ciphertext)
if detectEnglish.isEnglish(decryptedText, wordPercentage=40):
print()
print('Possible encryption break:')
print('Key ' + str(word) + ': ' + decryptedText[:100])
print()
print('Enter D for done, or just press Enter to continue breaking:')
response = input('> ')
if response.upper().startswith('D'):
return decryptedText
if __name__ == '__main__':
main()
2.1.3 代码解释
- 打开字典文件并读取所有单词。
- 遍历每个单词,使用该单词作为密钥对密文进行解密。
-
使用
detectEnglish.isEnglish()函数检查解密后的文本是否看起来像英语。 - 如果是英语,提示用户确认是否找到正确的解密结果。
2.2 卡西斯基试验法
2.2.1 原理
卡西斯基试验法是一种更复杂的破解方法,它通过分析密文中的重复序列来确定密钥的长度。具体步骤包括:
1.
寻找重复序列
:在密文中找到至少三个字母的重复序列。
2.
计算间距
:计算每个重复序列之间的字母数。
3.
计算间距的因数
:找出所有间距的因数,最常见的因数可能是密钥的长度。
2.2.2 示例
假设我们有以下密文:
PPQCA XQVEKG YBNKMAZU YBNGBAL JON I TSZM JYIM. VRAG VOHT VRAU C TKSG. DDWUO XITLAZU VAVV RAZ C VKB QP IWPOU
去除非字母字符后,我们可以找到重复序列
VRA
、
AZU
和
YBN
,它们的间距分别为 8、8、24、32 和 48。这些间距的因数如下表所示:
| 间距 | 因数 |
| ---- | ---- |
| 8 | 2, 4, 8 |
| 24 | 2, 4, 6, 8, 12, 24 |
| 32 | 2, 4, 8, 16 |
| 48 | 2, 4, 6, 8, 12, 24, 48 |
通过统计因数的出现频率,我们可以发现 2、4 和 8 是最常见的因数,因此密钥的长度很可能是 2、4 或 8。
2.2.3 后续步骤
确定可能的密钥长度后,我们可以将密文按密钥长度分组,对每组进行频率分析,以确定每个子密钥。具体步骤如下:
1.
分组
:假设密钥长度为 4,我们可以将密文按每四个字母一组进行分组。
2.
频率分析
:对每组进行频率分析,尝试找到最可能的子密钥。
3.
组合子密钥
:将找到的子密钥组合成完整的密钥,对密文进行解密。
通过以上方法,我们可以逐步破解维吉尼亚密码,即使密钥是随机的字母组合。
3. 卡西斯基试验法的详细步骤与代码实现
3.1 寻找重复序列
在密文中寻找至少三个字母的重复序列是卡西斯基试验法的第一步。以下是一个简单的 Python 代码示例,用于找出密文中的重复序列及其间距:
def find_repeated_sequences(ciphertext):
sequences = {}
for i in range(len(ciphertext) - 2):
seq = ciphertext[i:i + 3]
if seq in sequences:
sequences[seq].append(i)
else:
sequences[seq] = [i]
repeated_sequences = {seq: indices for seq, indices in sequences.items() if len(indices) > 1}
spacings = {}
for seq, indices in repeated_sequences.items():
spacings[seq] = [indices[j + 1] - indices[j] for j in range(len(indices) - 1)]
return spacings
ciphertext = "PPQCAXQVEKGYBNKMAZUYBNGBALJONITSZMJYIMVRAGVOHTVRAUCTKSGDDWUOXITLAZUVAVVRAZCVKBQPIWPOU"
spacings = find_repeated_sequences(ciphertext)
print(spacings)
该代码通过遍历密文,找出所有至少三个字母的序列,并记录它们的出现位置。然后,计算每个重复序列的间距。
3.2 计算间距的因数
找出间距的因数是卡西斯基试验法的关键步骤之一。以下是一个计算因数的 Python 函数:
def get_factors(num):
factors = []
for i in range(2, num + 1):
if num % i == 0:
factors.append(i)
return factors
all_factors = []
for seq, seq_spacings in spacings.items():
for spacing in seq_spacings:
factors = get_factors(spacing)
all_factors.extend(factors)
factor_count = {}
for factor in all_factors:
if factor in factor_count:
factor_count[factor] += 1
else:
factor_count[factor] = 1
sorted_factors = sorted(factor_count.items(), key=lambda item: item[1], reverse=True)
print(sorted_factors)
该代码首先定义了一个
get_factors
函数,用于计算一个数的所有因数(不包括 1)。然后,遍历所有间距,计算它们的因数,并统计每个因数的出现次数。最后,按因数的出现频率进行排序。
3.3 按可能的密钥长度分组并进行频率分析
确定可能的密钥长度后,我们可以将密文按密钥长度分组,并对每组进行频率分析。以下是一个示例代码,假设密钥长度为 4:
import freqAnalysis, vigenereCipher
def get_nth_letters(ciphertext, start_index, key_length):
return ciphertext[start_index::key_length]
key_length = 4
for i in range(key_length):
sub_ciphertext = get_nth_letters(ciphertext, i, key_length)
best_score = 0
best_subkey = ''
for subkey in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
decrypted_message = vigenereCipher.decryptMessage(subkey, sub_ciphertext)
score = freqAnalysis.englishFreqMatchScore(decrypted_message)
if score > best_score:
best_score = score
best_subkey = subkey
print(f"Subkey for position {i + 1}: {best_subkey}, Score: {best_score}")
该代码定义了一个
get_nth_letters
函数,用于从密文中提取每隔
key_length
个字母的子串。然后,对每个子串进行 26 次解密(尝试所有可能的子密钥),并使用频率分析函数计算每个解密结果的匹配得分。最后,选择得分最高的子密钥作为该位置的最佳子密钥。
4. 总结
通过频率分析和卡西斯基试验法,我们可以有效地破解维吉尼亚密码。以下是整个破解过程的流程图:
graph TD;
A[获取密文] --> B[字典攻击];
B --> C{是否破解成功};
C -- 是 --> D[输出解密结果];
C -- 否 --> E[卡西斯基试验法];
E --> F[寻找重复序列];
F --> G[计算间距];
G --> H[计算间距的因数];
H --> I[确定可能的密钥长度];
I --> J[按密钥长度分组];
J --> K[频率分析确定子密钥];
K --> L[组合子密钥解密];
L --> M[输出解密结果];
整个破解过程可以总结如下:
1. 首先尝试使用字典攻击,如果密钥是英语单词,可能会快速破解。
2. 如果字典攻击失败,使用卡西斯基试验法:
- 寻找密文中的重复序列及其间距。
- 计算间距的因数,确定可能的密钥长度。
- 按可能的密钥长度分组,对每组进行频率分析,确定每个子密钥。
- 组合子密钥,对密文进行解密。
通过这些方法,我们可以在不知道密钥的情况下,尝试破解维吉尼亚密码。需要注意的是,这些方法并不是万能的,对于一些复杂的密钥或较短的密文,可能无法成功破解。但在大多数情况下,它们可以提供有价值的线索,帮助我们逐步揭开加密信息的面纱。
超级会员免费看
17

被折叠的 条评论
为什么被折叠?



