CTF之密码学(凯撒加密)
一、基本原理
凯撒加密是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。这个加密方法是以罗马共和时期凯撒的名字命名的,据说凯撒曾用此方法与其将军们进行联系。
二、加密与解密过程
-
加密过程:
- 将明文中的每个字母按照字母表顺序向后(或向前)偏移一个固定的位数(密钥)。
- 偏移后的字母即为密文中的对应字母。
- 加密过程可以表示为函数:E(x) = (x + key) mod n,其中E表示加密函数,x表示明文中的字母在字母表中的位置(A=0, B=1, ..., Z=25),key表示密钥,n表示字母表中的字母个数(对于英文字母表,n=26)。
-
解密过程:
- 解密是加密的反过程,即将密文中的每个字母按照字母表顺序向前(或向后)偏移一个固定的位数(密钥)。
- 偏移后的字母即为明文中的对应字母。
- 解密过程可以表示为函数:D(y) = (y - key) mod n,其中D表示解密函数,y表示密文中的字母在字母表中的位置。
三、特定凯撒密码
根据偏移量的不同,还存在若干特定的凯撒密码名称,如:
- 偏移量为10:Avocat(A→K)
- 偏移量为13:ROT13
- 偏移量为-5:Cassis(K→F,但此处以正向偏移量表示,即相当于从Z向前数5个字母到K的逆向过程,实际加密时仍按正向偏移处理)
- 偏移量为-6:Cassette(类似地,K→E的逆向过程)
四、密码破解
凯撒密码是一种非常容易破解的加密方式,原因如下:
- 凯撒密码的加密方式简单,且密钥空间有限(对于英文字母表,最多只有25种不同的偏移量)。
- 可以通过频率分析等方法来破解凯撒密码。例如,在英语中,字母E和T出现的频率特别高,而在法语中出现频率最高的字母是E。因此,可以分析密文中每个字母出现的频率,并将其与正常情况下的该语言字母表中所有字母的出现频率做比较,从而估计出正确的偏移量。
五、优缺点及应用
- 优点:算法简单,易于实现和理解。在古代,这种加密方法已经足够保护机密文档。
- 缺点:在现代,由于密钥空间有限且加密方式简单,凯撒密码已无法提供足够的安全性。因此,它不再适用于需要高度安全性的场合。
- 应用:凯撒密码通常被作为其他更复杂的加密方法中的一个步骤或教学示例来使用。例如,在维吉尼亚密码等更复杂的加密方法中,可能会使用到类似凯撒加密的替换步骤。此外,凯撒密码还在现代的ROT13系统中被应用(ROT13是一种特殊的凯撒密码,其偏移量为13)。
简单python破解已知位移量的程序
txt = input().strip()
n = int(input())
answer = ""
for i in txt:
if i.islower():
answer += chr(97 + (ord(i) + n - 97) % 26)
elif i.isupper():
answer += chr(65 + (ord(i) + n - 65) % 26)
else:
answer += i
print(answer)
简单python破解未知位移量的程序:只需在上面的for循环外再加一次1-25的循环即可,看哪个和答案相似就是那个,只不过时间有点慢
下面介绍更好的写法
带注释版
txt = input().strip()
# 保持lower和upper为列表
lower = [chr(i) for i in range(ord('a'), ord('z') + 1)]
upper = [chr(i) for i in range(ord('A'), ord('Z') + 1)]
for i in range(1, 26):
# 直接在列表上使用切片来创建循环移位的版本
lower_1 = ''.join(lower[i:] + lower[:i]) # 这里使用了join来演示,但实际上可以直接用于maketrans的映射
upper_1 = ''.join(upper[i:] + upper[:i])
answer = ""
# 注意:这里不需要将lower_1和upper_1连接后再与原始的lower和upper连接
# 因为maketrans期望的是两个等长的字符串,分别表示要替换的字符和替换成的字符
# 由于lower和upper已经是完整的字母表,我们只需要提供循环移位的部分即可(但长度必须相同)
# 然而,在这个特定的例子中,为了简单起见,我们可以直接使用完整的循环移位字符串与原始字符串进行映射
# 但这实际上是不必要的,因为我们只需要确保映射是正确的即可
# 下面的代码是简化的,并且是正确的,因为它确保了映射的字符数量是相同的
table = ''.maketrans(''.join(lower_1), ''.join(lower)) # 只映射小写字母
table.update(''.maketrans(''.join(upper_1), ''.join(upper))) # 更新映射以包含大写字母
# 注意:上面的两行可以合并为一行,但为了清晰起见,这里分开写了
# table = ''.maketrans(''.join(lower_1+upper_1), ''.join(lower+upper))
# 或者,更简洁但可能不太直观的方法是:
# 由于lower和upper已经是完整的,我们可以直接创建一个完整的映射表,然后忽略未使用的字符
# table = ''.maketrans(''.join(lower_1 + upper_1), ''.join(lower + upper))
# 但这种方法在理论上是有效的,因为它确保了所有可能的字符都有一个映射(尽管有些映射是冗余的)
# 更优化的方法是只创建一个映射,该映射仅包含实际会改变的字符
# 由于凯撒密码只改变字母,我们可以只映射字母,并允许其他字符(如标点符号、数字等)保持不变
# 但为了与您的原始代码保持一致,并展示如何使用maketrans,这里我们还是使用上面的方法
for j in txt:
# 检查字符是否在映射表中,如果是,则进行替换;如果不是(如标点符号、数字等),则保持不变
# 这在上面的映射方法中已经隐含处理了,因为未映射的字符将保持不变
answer += j.translate(table)
print(answer)
不带注释版
txt = input().strip()
lower = [chr(i) for i in range(ord('a'),ord('z')+1)]
upper = [chr(i) for i in range(ord('A'),ord('Z')+1)]
for i in range(1,26):
lower_1 = lower[i:] + lower[:i]
upper_1 = upper[i:] + upper[:i]
answer = ""
table = ''.maketrans(''.join(lower_1+upper_1), ''.join(lower+upper))
# table.update(''.maketrans(''.join(upper_1), ''.join(upper))) #
for j in txt:
answer += j.translate(table)
print(answer)