根据2022培养方案,笔者在秋季学期学习了密码学课程,其中新增的实验颇有意思,记录其中的思考。您可以查看我的代码
密码学实验
LAB1
如果使用ascii编码 一个字母和空格异或会改变大小写
在ASCII编码中,字母和空格字符进行异或操作会改变字母的大小写,这是因为ASCII值之间的特定数学关系。
ASCII码表中,大写字母A到Z的值从65到90,而小写字母a到z的值从97到122。你会注意到,任何一个大写字母与任何一个小写字母之间的差异恰好是32。空格字符的ASCII值是32,二进制表示为00100000。
当你对一个字母字符进行异或操作,实际上是在对该字符的二进制表示进行操作。异或操作的规则是:如果两个比较的位不同,则结果为1;如果相同,则结果为0。所以,当你把一个字母与32进行异或操作时,只有第六位(从右往左数)会发生改变(0变1或1变0),因为32的二进制表示中只有第六位是1,其他都是0。这个改变恰好足以将大写字母转换为小写字母,或者将小写字母转换为大写字母。
举个例子,字母**A
的ASCII值是65,二进制表示为01000001
。字母a
的ASCII值是97,二进制表示为01100001
。你可以看到,它们只在第六位有差异。如果你对A
(01000001
)和空格(00100000
)进行异或操作,结果是01100001
,这恰好是a
**的ASCII编码。
因此,一个字母和空格字符进行异或操作的结果是改变该字母的大小写,这一特性被广泛应用于密码学中,特别是在分析使用相同密钥加密多个明文的加密策略时。
一个Many Time Pad Attack的思路
LAB2
必要假设
整个实验,假设通信的双方已经同步了初始向量和所有秘钥。在实验过程中简化为将iv,key,以及mac等秘钥保存在key目录下,以模拟双方都同步了秘钥。
本次实验主要是针对图片内容加密,因此不能对图片文件格式造成破坏以至于无法打开,同时针对密文的攻击也以对内容部分的攻击为主.
假设敌手知道加密方案。(其实不知道也行,因为翻转密文的特定位也能被解密,也能看关系)
CPA加密
采用OFB加密块加密方案。利用AES做为PRP,生成伪随机数,由于敌手无法预测初始向量的规律,因此随机数与真随机数的差异可忽略。
为了实验的封装性,将CPA和第三问的CCA封装成class,这样也便于写解密预言机
实验思路
- 图片的选择
我们都知道,所谓图片其实就是bytes矩阵,由于本次实验选择的图片带有颜色,因此选用颜色空间为RGB的png图片作为实验加解密主要对象。python
中提供了相当多的图片处理库,常见的有pillow
和PIL
,本实验选择PIL
from PIL import Image
然后使用上下文来读取rgb三色空间
with Image.open(input_path) as img:
r, g, b = img.split()
这样,在整个上下文空间中,我们就有了img
对象
然后,利用image
(因为这个便于后续做异或,以及slice,而且其实是作者用的比较熟悉())
r_processed = self._encrypt_schema(np.array(r, dtype=np.uint8).tobytes())
g_processed = self._encrypt_schema(np.array(g, dtype=np.uint8).tobytes())
b_processed = self._encrypt_schema(np.array(b, dtype=np.uint8).tobytes())
这个解密 首先要在初始过程中设置好加解密器,
def __init__(self, key_path=r"lab2\key\key.bin", iv_path=r"lab2\key\iv.bin"):
# 生成或读取密钥和IV
if not os.path.exists(key_path) or not os.path.exists(iv_path):
self.key = os.urandom(32) # AES-256要求的密钥长度
self.iv = os.urandom(16) # OFB模式的IV大小
with open(key_path, "wb") as key_file:
key_file.write(self.key)
with open(iv_path, "wb") as iv_file:
iv_file.write(self.iv)
self.cipher = Cipher(algorithms.AES(self.key), modes.OFB(self.iv), backend=default_backend())
else:
with open(key_path, "rb") as key_file:
self.key = key_file.read()
with open(iv_path, "rb") as iv_file:
self.iv = iv_file.read()
self.cipher = Cipher(algorithms.AES(self.key), modes.OFB(self.iv), backend=default_backend())
如图,利用Cipher(algorithms.AES(self.key), modes.OFB(self.iv), backend=default_backend())
来创建一个对象,通过调用对象中的encryptor = self.cipher.encryptor()
来创建加密器,decryptor = self.cipher.decryptor()
来创建解密器,
decryptor.update(image) + decryptor.finalize()
在密码学中,特别是在使用对称加密算法如AES进行加密和解密时,finalize
方法的作用是完成加解密过程的最后一步。这个方法通常在处理完所有的数据块后被调用,以确保所有的加密或解密操作都已经完成,包括处理任何剩余的数据(例如,在加密模式需要填充的情况下)以及执行必要的清理和状态重置。
具体到decryptor.update(image) + decryptor.finalize()
这个表达式,这是在使用一个加密库(如Python中的cryptography库)时,进行解密操作的典型步骤。这里,decryptor
是一个解密器对象,它负责对密文进行解密操作。这个过程通常分为两步:
- 更新(update):
decryptor.update(image)
这部分负责处理大部分的密文数据。update
方法可以被多次调用,用于逐步处理密文。在流式加密或者需要分块处理大量数据的场景中,这允许数据被逐块处理,而不是一次性加载到内存中。 - 完成(finalize):
decryptor.finalize()
这部分则标志着解密操作的结束。调用finalize
方法以完成解密过程,处理可能的最后一个数据块,并且在某些情况下(如需要去除填充)进行必要的后处理。一旦调用了finalize
方法,解密器对象通常就不能再被用于解密其他数据块。
组合使用update
和finalize
方法提供了一种灵活处理加解密操作的方式,特别是在处理大量数据或者需要根据数据流动态加解密时。这种模式不仅适用于解密,同样适用于加密过程。
这样,加密之后没有破坏png的原始结构,但是将png的内容进行隐藏。
对CPA加密,利用CCA攻击
CPA类提供接口
def _decrypt_schema(self, image):
decryptor = self.cipher.decryptor()
return decryptor.update(image) + decryptor.finalize()
调用时仅需
cca.encrypt_image(r'lab2\img\微信图片_20240328235356.jpg', r'lab2\img\avatarencCCA.png')
可见,函数的参数仅仅就是图片的路径而已,因此IV和Key是被隐藏的。
这也是将加密方案封装起来的原因,(因为在CCA攻击的代码下放着IV 和key总觉得不是很优雅),这样实现的Oracle为
def decrypt_oracle(input_file, output_file):
cpa = CPA()
return cpa.decrypt_image(input_file, output_file)
这就很优雅
我们知道,在CCA敌手下,挑战过程中,敌手可以问oracle所有除了已知密文的所有密文,从而获得对应的明文, 由于上面的方案是CPA安全而不是CCA安全(密文没有不可锻造性),所以敌手可以通过篡改密文中的比特来让oracle给他解密,由于这是个图片,跟以前的实验仅仅是字符串不一样,单独解密一两个bit很难看出有什么端倪,因此反正敌手都这么强了,不如干票大的:
将图片上半部分比特取反,然后解密,输出,再将下半部分比特取反,解密,然后将这两个图片下部分和上部分拼接,就得到了最终的明文。
根据OFB的方案,我们将IV丢到F中,会得到一堆生成好的F的输出,然后和明文$m_x$异或。
如果解密,采用同一个IV,那么F输出的那一堆向量不变,将篡改后的密文$c^’_i$和结果异或,可以发现其实颜色被取反了(因为异或的输入有一个取反有一个不变,结果也相当于取反)。也能获得一些信息。但是其余没有篡改的部分会被正常解密,那那些部分就可以被利用起来。
所以我们将这些部分拼凑起来就可以得到最终的明文。
如果是CBC
就可以
- 选择目标块:决定你想要修改的密文块。如果你修改第N个块的密文,那么这个修改会直接影响第N+1个块的明文(由于CBC的XOR特性)。
- 执行修改:执行实际的修改,比如可以通过XOR操作对选定的密文块中的一些位进行反转。
- 观察结果:解密修改后的密文,并观察如何影响明文。特别是观察被直接修改的块和其后一个块的变化。
CCA加密方案
CCA之所以能对CPA安全的加密方案进行攻击的主要原因是因为,加密方案在解密过程中无法得知,输入的密文是否已经被篡改。因此我们可以给方案加上一个验证,当发现密文被篡改了的时候,就抛出异常,由此我们想到最近学的MAC和CRHF。
PNG文件结构
https://blog.csdn.net/szzheng/article/details/105177740
我们在对图片加密的时候,先利用PIL加载图片,在RGB三个通道下对内容进行加密,然后在对图片的内容做一个MAC,生成一个标签,然后将标签放在pnginfo上和生成的加密png一起保存。
在解密的时候,我们首先对png的内容生成一个mac,然后提取出png文件特定位置的mac,对这两个mac做校验,如果mac不一致,那么就说明图片的内容被敌手篡改,否则验证通过,开始解密。
def _add_mac_chunk(self, image, mac):
metadata = PngImagePlugin.PngInfo()
metadata.add_text("MAC", mac.hex())
image.save("temp.png", pnginfo=metadata)
return Image.open("temp.png")
def _get_mac_from_chunk(self, image):
metadata = image.info
return bytes.fromhex(metadata.get("MAC", ""))
def _generate_image_mac(self, image_data):
# 生成图像内容的 MAC
h = hmac.new(self.mac_key, msg=image_data, digestmod=hashlib.sha256)
return h.digest()
Lab3
针对RSA的一些攻击的文章链接
RSA的攻与防(一) | 网络热度 (packetmania.net)
二十年以来对 RSA 密码系统攻击综述 (seebug.org)
Lab4
TLS1.3协议
https://www.cnblogs.com/informatics/p/17545403.html
WireShark
https://blog.csdn.net/zzwwhhpp/article/details/113077747?spm=1001.2014.3001.5506
HIT·2024 密码学期末考试掠影
期末考试中,原题数量依然不少,但是对于每个实验都进行了考察,因此复习时应当注意。 笔者印象深刻的是:
- X509证书中,_______字段代表自己的域名
- 在实验三中,你如何确定
p
和q
因子。 - 在实验二中,你是用的________方案实现的CCA安全。 此外,最后一道大题是简述TLS协议及配置证书的整个过程。