Invert
雪 币: 502
活跃值: (205)
能力值:
( LV3,RANK:20 )
在线值:
本文接 上一篇,这次我们在功耗分析的基础上更进一步,尝试一下用差分功耗分析(Differential Power Analysis),更具体地说,应该是相关性功耗分析(Correlation Power Analysis),来破译 AES-128 密码。
上一篇 我们提出并验证了一个简单的假设:CPU 在执行不同种类的指令的时候会产生不同形状的功耗信号特征,从而泄漏不同指令的执行次数。但是,仅仅看功耗信号的形状,我们很难辨认出指令操作的具体数据。比方说 1+1
和 2+2
在功耗信号上都是差不多的形状,那么问题来了:能不能进一步分析功耗信号,提取出 CPU 计算的具体数据值呢?
这里我们给出一个进一步的假设:CPU 计算的数值(输入值或者输出值都行)的汉明重量(Hamming Weight),也就是二进制表达下,1 出现的次数,与该计算的某一时间点上的功耗值成线性关系。这一假设的根据在于,CPU 内部用来表达 0 和 1 的数据线路上触发的半导体数量不同,导致功耗不同。在某一时间点上,CPU 需要在多个数据线路上完整表达计算值的每一个比特,因此这个时间点的功耗跟数值的汉明重量应成线性关系。
我们接下来设计一个实验来验证我们的假设。
我们这个实验将使用一个简单的纯软件实现的 Single Block AES 加密程序用来作为测试和测量功耗数据。这个程序从串口读取一个 16 bytes 的 AES-128 密钥,以及一个 16 bytes 的明文数据。然后它会使用提供的密钥对提供的明文进行加密,然后由串口输出加密后的 16 bytes 密文数据。也就是说加密用的密码是我们设置的,这个在现实中往往都是固件里头或者芯片里面写死的我们访问不到,但由于我们现阶段主要是验证理论猜想,我们可以通过控制已知的密钥和明文,观察我们的数据是否符合我们的假设。
我们将采集两组数据:
然后我们对每组数据的 50 个功耗图进行叠加求平均得到每个组一个平均功耗变化图,红色的是第一组数据的平均图,绿色的是第二组数据的平均图:
我们可以观察到,明文值的改变对功耗特征的形状也有影响,可以明显看出来两组数据有平移的关系。我们需要把第二组数据向后平移跟第一组数据对齐然后切掉第一组数据开头的部分。我们可以通过上一篇介绍的 SAD 统计方法找到需要位移的量。这里就不详细展开了,处理完后我们得到这样的图像:
可以看到两组数据在时间点上都对齐了。然后我们可以简单地把两组平均图像上的对应点相减,得到一个差值图像:
这个差值图像可以将两组数据中的微小差异放大。我们可以很容易地观察到明显的几处突起,说明这几个时间点上,输入数据的第一个 Byte 的汉明重量确实对功耗有一定的可观测到的影响。
但是这只验证了我们一半的假设,我们仍需要进一步验证汉明重量跟功耗成线性关系。对此,我们可以使用皮尔逊积矩相关系数(Pearson Correlation Coefficient)指标作为我们衡量线性关系的基础,这个指标越接近 ±1,线性关系越强,越接近 0 则线性关系越弱。
这次我们先生成测试数据,采集完功耗数据之后再进行分组。每次运行我们都生成一组随机的密钥和明文,这次就不改动生成的明文了,然后直接进行加密和测量功耗数据。如此运行采集 1000 份数据。
我们知道,AES 最基本的运算单元之一是 ,其中,是明文的第i个byte,而是密钥的第i个byte,S是S-Box查表操作。
因为我们知道每份数据的密钥,我们可以手动计算出第一个计算单元的输出值,计算这个输出的汉明重量,那么对于每一个汉明重量值(0-8)、在每一个时间点上我们都能提取出采集到的功耗数据,然后计算出这个时间点上,该汉明重量对应的平均的功耗值。
然后我们可以在每一个时间点上,通过得出的 汉明重量-平均功耗值 表格数据,进一步计算出皮尔逊积矩相关系数。这个指标代表了,这个时间点上,汉明重量和平均功耗值的线性关系程度。最后我们将每个时间点上的皮尔逊积矩相关系数画出来,得到这样一张图像:
可以看到有很多突起都非常接近 ±1,这表明了上述计算单元的输出值与功耗存在线性关系性。至此,我们完整验证了我们提出的假说。
理论根据有了,如何设计一个完整的攻击呢?首先我们要认识到,在实际的攻击场景中,我们是不知道密钥是什么的,也不知道加密过程中间的计算单元的实际输出值。但是,我们可以一个个 byte 地对密钥进行 brute-force:密钥的每一个 byte 我们尝试 0x00-0xFF 一共 255 种数值的可能性,对每一个尝试,我们可以结合我们采集数据时使用的明文,算出上述基础 AES 计算单元的输出的汉明重量,然后我们都找出最大的关系性指标值,然后取关系性最大的那个尝试的值即可。
下图给出的是正在爆破单个 byte 时候计算出来的关系性指标,红色的是正确的密钥值,绿色的则是别的不正确的密钥值计算出来的图。我们可以很清楚地看到,最大的关系性出现在红色数据中,由此我们可以确定红色数据所尝试的 byte 的值是正确的密钥的一个 byte。
然后把这个过程重复到密钥的每个 byte 上,下图我们把每个 byte 试出来的最大关系性出现的图像叠加起来,组成一个比较明显的特征图:
可以看到,每个 byte 的关系性突起都分布得非常均匀,这恰好也符合我们的预期,因为我们的 AES 运行方式就是一个个 byte 地进行计算的。
这样我们就得到了完整的 AES 密钥了。如果你想尝试这个攻击的话可以使用 jupyter/PA_CPA_1-Using_CW-Analyzer_for_CPA_Attack.ipynb
这个文件,基本上只要采样 50 份功耗数据就能完成 AES-128 密钥的破译了。
这次介绍了如何通过数据汉明重量和功耗的线性关系性来破译 AES 密钥。下一次将开始进入有源侧信道攻击的探索之旅——毛刺攻击(Glitching),敬请期待。