补一期,光学理论不写码,等于白学,随便写了点,便于自己加深理解
## Cacsar
编写一个加密解密程序实现广义Cacsar密码
广义的Caesar密码,也就是加法密码,是一种简单的加密算法,它通过将字母表中的每个字母移动固定数目的位置来进行加密。
例如,如果移动的数目是3,那么'A'就会变成'D','B'变成'E',以此类推。当到达字母表的末尾时,它会循环回到开头。
python代码
def caesar_encrypt(text, shift):
encrypted_text = ""
for char in text:
if char.isalpha(): # 检查字符是否是字母
shifted = ord(char) + shift
if char.islower():
if shifted > ord('z'):
shifted -= 26
elif shifted < ord('a'):
shifted += 26
elif char.isupper():
if shifted > ord('Z'):
shifted -= 26
elif shifted < ord('A'):
shifted += 26
encrypted_text += chr(shifted)
else:
encrypted_text += char # 非字母字符不变
return encrypted_text
def caesar_decrypt(encrypted_text, shift):
return caesar_encrypt(encrypted_text, -shift)
# 使用示例
original_text = "Hello, World!"
shift_amount = 3
encrypted = caesar_encrypt(original_text, shift_amount)
decrypted = caesar_decrypt(encrypted, shift_amount)
print("Original: ", original_text)
print("Encrypted: ", encrypted)
print("Decrypted: ", decrypted)
caesar_encrypt 函数用于加密文本,而 caesar_decrypt 函数则用于解密文本。
shift 参数是字母表中字母移动的数目。加密函数会遍历文本中的每个字符,如果字符是字母,就将其ASCII值加上 shift 的值,如果超出了字母表的范围,就通过减去或加上26来循环回到字母表的开头。非字母字符在加密和解密过程中保持不变。
## 仿射密码
仿射密码是一种单字母替换密码,它使用以下公式进行加密:
$$\it E(x)=(ax+b)\mod m$$
E(x) 是加密后的值。
x 是明文中字母的数值(例如,A=0, B=1, ..., Z=25)。
a 和 b是密钥,a 必须与 m互质gcd(a,m)=1
m 是字母表的大小(对于英文字母表,m=26)
解密公式是
$$D(y) = a^{-1} (y - b) \mod m$$
$$
a^{-1} \text{ 是 } a \text{ 在模 } m \text{ 下的乘法逆元,即 } a \cdot a^{-1} \equiv 1 \mod m。$$
python
def find_multiplicative_inverse(a, m):
# 使用扩展欧几里得算法找到a在模m下的乘法逆元
def extended_gcd(a, b):
if a == 0:
return b, 0, 1
else:
gcd, x, y = extended_gcd(b % a, a)
return gcd, y - (b // a) * x, x
gcd, x, y = extended_gcd(a, m)
if gcd != 1:
raise Exception('a and m are not coprime')
else:
return x % m
def affine_encrypt(text, a, b):
encrypted_text = ""
for char in text:
if char.isalpha():
shifted = ord(char.lower()) - ord('a')
encrypted = (a * shifted + b) % 26
encrypted_text += chr(encrypted + ord('a'))
else:
encrypted_text += char
return encrypted_text
def affine_decrypt(encrypted_text, a, b):
inverse_a = find_multiplicative_inverse(a, 26)
decrypted_text = ""
for char in encrypted_text:
if char.isalpha():
shifted = ord(char.lower()) - ord('a')
decrypted = (inverse_a * (shifted - b)) % 26
decrypted_text += chr(decrypted + ord('a'))
else:
decrypted_text += char
return decrypted_text
# 使用示例
original_text = "Hello, World!"
key_a = 5
key_b = 8
encrypted = affine_encrypt(original_text, key_a, key_b)
decrypted = affine_decrypt(encrypted, key_a, key_b)
print("Original: ", original_text)
print("Encrypted: ", encrypted)
print("Decrypted: ", decrypted)
ffine_encrypt 函数用于加密文本,而 affine_decrypt 函数则用于解密文本。find_multiplicative_inverse 函数使用扩展欧几里得算法来找到 a 在模 m 下的乘法逆元。
## 加法密码进行字母频率攻击
写一个程序,无须人工干预,对加法密码实现字母频率攻击。软件按可能性大小的顺序给出可能的
明文。如果用户界面允许用户定义“给出前10个可能明文”,则更好
要实现一个对加法密码进行字母频率攻击的程序,我们需要遵循以下步骤:
频率分析:计算密文中每个字母的频率,并将其与英语字母表中字母的频率进行比较。
猜测移位:根据频率分析,猜测可能的移位量。
解密尝试:对每个猜测的移位量进行解密尝试。
评估结果:评估解密文本的质量,例如通过检查常见的英语单词来确定最可能的明文。
排序结果:根据某种标准(如卡方统计量)对可能的明文进行排序。
python
import string
from collections import Counter
import re
# 英语字母表中字母的频率
ENGLISH_FREQ = {
'E': 12.70, 'T': 9.06, 'A': 8.17, 'O': 7.51, 'I': 6.97, 'N': 6.75, 'S': 6.33,
'H': 6.09, 'R': 5.99, 'D': 4.25, 'L': 4.03, 'C': 2.78, 'U': 2.76, 'M': 2.41,
'W': 2.36, 'F': 2.23, 'G': 2.02, 'Y': 1.97, 'P': 1.93, 'B': 1.29, 'V': 0.98,
'K': 0.77, 'J': 0.15, 'X': 0.15, 'Q': 0.10, 'Z': 0.07
}
def calculate_frequency(text):
return Counter(c for c in text if c.isalpha())
def caesar_decrypt(encrypted_text, shift):
decrypted_text = ""
for char in encrypted_text:
if char.isalpha():
shifted = ord(char) - shift
if char.islower():
if shifted < ord('a'):
shifted += 26
elif char.isupper():
if shifted < ord('A'):
shifted += 26
decrypted_text += chr(shifted)
else:
decrypted_text += char
return decrypted_text
def chi_square(observed, expected):
return sum((o * (o - e) ** 2) / e for o, e in zip(observed, expected))
def score_text(text):
freqs = calculate_frequency(text.lower())
expected = {char: ENGLISH_FREQ[char] / sum(ENGLISH_FREQ.values()) for char in ENGLISH_FREQ}
return chi_square(freqs.values(), expected.values())
def break_caesar_cipher(encrypted_text):
possible_shifts = range(26)
possible_texts = [caesar_decrypt(encrypted_text, shift) for shift in possible_shifts]
scores = [(score_text(text), text) for text in possible_texts]
return sorted(scores, key=lambda x: x[0])
# 使用示例
encrypted_text = "Bmfs gqfbsy!"
top_n = 10
results = break_caesar_cipher(encrypted_text)
for score, text in results[:top_n]:
print(f"Score: {score:.2f}, Text: {text}")
calculate_frequency 函数计算文本中每个字母的频率。
caesar_decrypt 函数对给定的密文进行解密,移位量为 shift。
chi_square 函数计算卡方统计量,用于评估解密文本的质量。
score_text 函数使用卡方统计量对文本进行评分。
break_caesar_cipher 函数尝试所有可能的移位量,解密密文,并根据评分对结果进行排序。
## 单表代替
写一个程序,无须人工干预,对单表代替密码实现字母频率攻击。软件按可能性大小的顺序给出可
能的明文。如果用户界面允许用户定义“给出前10个可能明文”,则更好。
单表代替密码(也称为简单替换密码)是一种密码,其中明文中的每个字母被替换为密文中的一个固定字母。要对这种密码进行频率分析,我们需要:
频率分析:计算密文中每个字母的频率,并将其与英语字母表中字母的频率进行比较。
匹配频率:将密文中频率最高的字母与英语中频率最高的字母(通常是'E')匹配,依此类推。
构建替换表:根据频率匹配构建替换表。
解密文本:使用替换表解密整个密文。
评估结果:评估解密文本的质量,例如通过检查常见的英语单词来确定最可能的明文。
排序结果:根据某种标准(如卡方统计量)对可能的明文进行排序。
python
import string
from collections import Counter
import itertools
# 英语字母表中字母的频率
ENGLISH_FREQ = {
'E': 12.70, 'T': 9.06, 'A': 8.17, 'O': 7.51, 'I': 6.97, 'N': 6.75, 'S': 6.33,
'H': 6.09, 'R': 5.99, 'D': 4.25, 'L': 4.03, 'C': 2.78, 'U': 2.76, 'M': 2.41,
'W': 2.36, 'F': 2.23, 'G': 2.02, 'Y': 1.97, 'P': 1.93, 'B': 1.29, 'V': 0.98,
'K': 0.77, 'J': 0.15, 'X': 0.15, 'Q': 0.10, 'Z': 0.07
}
def calculate_frequency(text):
return Counter(c for c in text if c.isalpha())
def decrypt_text(encrypted_text, mapping):
decrypted_text = ""
for char in encrypted_text:
if char in mapping:
decrypted_text += mapping[char]
else:
decrypted_text += char
return decrypted_text
def chi_square(observed, expected):
return sum((o * (o - e) ** 2) / e for o, e in zip(observed, expected))
def score_text(text):
freqs = calculate_frequency(text.lower())
expected = {char: ENGLISH_FREQ[char] / sum(ENGLISH_FREQ.values()) for char in ENGLISH_FREQ}
return chi_square(freqs.values(), expected.values())
def break_substitution_cipher(encrypted_text):
possible_mappings = itertools.permutations(string.ascii_lowercase, 26)
possible_texts = [decrypt_text(encrypted_text, mapping) for mapping in possible_mappings]
scores = [(score_text(text), text) for text in possible_texts]
return sorted(scores, key=lambda x: x[0])
# 使用示例
encrypted_text = "Bmfs gqfbsy!"
top_n = 10
results = break_substitution_cipher(encrypted_text)
for score, text in results[:top_n]:
print(f"Score: {score:.2f}, Text: {text}")
calculate_frequency 函数计算文本中每个字母的频率。
decrypt_text 函数使用给定的映射表解密文本。
chi_square 函数计算卡方统计量,用于评估解密文本的质量。
score_text 函数使用卡方统计量对文本进行评分。
break_substitution_cipher 函数尝试所有可能的字母映射,解密密文,并根据评分对结果进行排序。
## Hill密码
2×2 Hill密码是一种使用2×2矩阵和模运算的多字母替换密码。它使用一个密钥矩阵和一个模26的乘法逆元来加密和解密文本。
首先,我们需要定义一些辅助函数来处理模运算和矩阵操作:
python
import numpy as np
#找到模26下的乘法逆元
def find_inverse(modulus, number):
for x in range(1, modulus):
if (number * x) % modulus == 1:
return x
return None
# 模26下的矩阵乘法
def mod_mul_matrix(a, b, mod):
return np.dot(a, b) % mod
# 模26下的矩阵乘法逆元
def mod_inverse_matrix(matrix, mod):
det = np.linalg.det(matrix)
inv_det = find_inverse(mod, det)
inv_matrix = np.linalg.inv(matrix) * inv_det
return np.round(inv_matrix).astype(int)
# 加密一对字母
def encrypt_pair(plain_pair, key_matrix):
return mod_mul_matrix(key_matrix, np.array(plain_pair), 26)
# 解密一对字母
def decrypt_pair(cipher_pair, inv_key_matrix):
return mod_mul_matrix(inv_key_matrix, np.array(cipher_pair), 26) % 26
现在,我们可以定义加密和解密函数:
def hill_encrypt(plain_text, key_matrix):
encrypted_text = ""
for i in range(0, len(plain_text), 2):
pair = plain_text[i:i+2]
num_pair = [ord(char) - ord('A') for char in pair]
cipher_pair = encrypt_pair(num_pair, key_matrix)
encrypted_text += ''.join(chr(code + ord('A')) for code in cipher_pair)
return encrypted_text
def hill_decrypt(cipher_text, inv_key_matrix):
decrypted_text = ""
for i in range(0, len(cipher_text), 2):
pair = cipher_text[i:i+2]
num_pair = [ord(char) - ord('A') for char in pair]
plain_pair = decrypt_pair(num_pair, inv_key_matrix)
decrypted_text += ''.join(chr(code + ord('A')) for code in plain_pair)
return decrypted_text
最后,我们需要一个密钥矩阵及其逆元来测试这些函数:
# 定义一个密钥矩阵
key_matrix = np.array([[2, 3], [5, 7]])
# 找到模26下的密钥矩阵逆元
inv_key_matrix = mod_inverse_matrix(key_matrix, 26)
# 测试加密和解密
plain_text = "HELLO"
cipher_text = hill_encrypt(plain_text, key_matrix)
decrypted_text = hill_decrypt(cipher_text, inv_key_matrix)
print("Plain Text:", plain_text)
print("Cipher Text:", cipher_text)
print("Decrypted Text:", decrypted_text)