侧信道实验实验二 S盒DPA侧信道攻击

---------------------------------------202/12/19 更新---------------------------------------
在输入时除了密钥的遍历范围因为DES的S盒的“6进4出“机制导致范围限定在0-63以外,明文在作为S盒输入的时候也是被限制在每组长度为64。我将明文数组长度从1000更新为64后的猜测正确率也是100%。
-------------------------------------------起始内容-------------------------------------------

实验目的

  1. 掌握S盒侧信道攻击的基本原理;
  2. 掌握汉明重量攻击模型;
  3. 掌握DPA攻击基本原理和方法。

实验人数

每组1人

系统环境

Windows

实验原理

  1. 测量阶段,选取随机数量明文和设定好的正确密钥进行异或,得到的6bit结果作为S盒的输入,S盒的输出需统计二进制中1的个数,作为汉明重量,所有输出得到一个汉明重量数组。
  2. 攻击阶段,需要遍历密钥的所有可能,每次遍历都需经历测量阶段,最后得到所有猜测密钥的汉明重量数组,且每个都需要计算数组元素中间值,作为划分正确密钥得到的汉明重量数组的依据,正确密钥得到的汉明重量数组划分成两个集合,分别计算 x H ‾ = 1 ∣ H ∣ ∑ i ∈ H x i \overline{x_H}=\frac{1}{\lvert H \rvert}\sum_{i\in H}^{}{x_i} xH=H1iHxi x L ‾ = 1 ∣ L ∣ ∑ i ∈ L x i \overline{x_L}=\frac{1}{\lvert L \rvert}\sum_{i\in L}^{}{x_i} xL=L1iLxi,其中 ∣ ∣ || 表示集合元素大小,得到差值求均值差 D p a V a l u e = x H ‾ − x L ‾ DpaValue=\overline{x_H}-\overline{x_L} DpaValue=xHxL,最后选择所有差值最大的所对应的猜测密钥为正确密钥。

实验内容

  1. 完成Sboxdpa仿真-student.py程序中的空缺部分

    • 补充n、plaintext、keyTrue

    • 补充HWfun函数,返回输入的汉明重量

    • 补充主函数,得到输出相应的汉明重量向量

  2. 完成Sboxdpa-student.py文件中的空缺部分,即

    • 补充plaintext、power_std

    • 补充DPAfun函数,计算汉明差值

    • 补充主函数,求正确猜测密钥

  3. 实验测试2组数据

实验步骤

完善Sboxdpa仿真-student.py程序

补充变量

补充n、plaintext、keyTrue三个变量

n = 9	#数组长度
plainlist = [41, 35, 62, 4, 33, 44, 22, 46, 18]	#明文数组
keyTrue = 43	#加密所用密钥
完善HWfun函数

本质上是计算十进制数转换成二进制后含1的数量,则可以采用快速法计算。这种方法运算次数与输入n的大小无关,只与n中1的个数有关。如果n的二进制表示中有k个1,那么这个方法只需要循环k次即可。其原理是不断清除n的二进制表示中最右边的1,同时累加计数器,直至n为0。

补充代码如下:

def HWfun(num):
    # 统计输入num的汉明重量并返回
    ans = 0
    if num == 0:
        return 0
    while num > 0:
        num &= (num - 1)
        ans += 1
    return ans

为什么n &= (n – 1)能清除最右边的1呢?因为从二进制的角度讲,n相当于在n - 1的最低位加上1。举个例子,8(1000)= 7(0111)+ 1(0001),所以8 & 7 = (1000)&(0111)= 0(0000),清除了8最右边的1(其实就是最高位的1,因为8的二进制中只有一个1)。再比如7(0111)= 6(0110)+ 1(0001),所以7 & 6 = (0111)&(0110)= 6(0110),清除了7的二进制表示中最右边的1(也就是最低位的1)。

完善主函数

使用表格美化库完善输出。

补充代码如下:

if __name__ == "__main__":
    # 补充:S盒输出对应汉明重量列表
    table = pt.PrettyTable()
    hw_std = []
    HWout = sboxout(n, plainlist, keyTrue)
    for i in range(n):
        hw_std.append(HWfun(HWout[i]))
    table.add_column('序号',[i for i in range(1,n+1)])
    table.add_column('明文-十进制',[index for index in plainlist])
    table.add_column('S盒输出-十进制', [index for index in HWout])
    table.add_column('S盒输出-汉明重量', [index for index in hw_std])
    print(table)
程序运行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
在这里插入图片描述

图6.1     程序Sboxdpa仿真-student.py的表格输出

完善Sboxdpa-student.py程序

补充变量

我在此程序中采用的plaintlist数组(明文数组)是由plainlist = list(np.random.randint(64, size=1000))函数生成的1000长度的数组,模拟教材上的运行基数。同理,power_std数组(正确密钥处理得到的汉明重量数组)同样长度1000,数组内的元素展示位置在8.4数据统计中,“明文数组长度为1000”那里。

完善DPAfun函数

Meanfun函数我有所改动:

def Meanfun(num):
    total = 0
    length = len(num)
    if length == 0:
        return 0
    for i in range(length):
        total = total + num[i]
    return total / length

函数思想是取使用猜测密钥处理的汉明重量数组的中间值作为划分使用正确密钥处理的汉明重量数组的依据,随后,函数返回划分后集合的差值。

补充代码如下:

def DPAfun(n, pstd, ptest):
    # 以2为界,计算不同汉明重量的集合差值
    L_list = []
    H_list = []
    med = median(ptest)
    for i in range(n):
        if ptest[i] <= med:
            L_list.append(pstd[i])
        else:
            H_list.append(pstd[i])
    return Meanfun(H_list) - Meanfun(L_list)
完善主函数

运行逻辑&思路为遍历所有密钥——64个,将明文和每个密钥异或后的结果作为S盒的输入,得到S盒的输出(模拟DES处理流程),并求得64个汉明重量数组,将64个汉明重量数组带入DPAfun函数进行运算,取DPAfun函数返回值中的最大值对应的密钥,即为正确密钥。

因为DES的S盒运算是“6进4出”的,明文和密钥的异或是在进入S盒前,要满足6位输入的需求,所以密钥遍历是2的六次方次。

补充代码如下:

if __name__ == "__main__":
    # 猜测密钥
    keyList = [i for i in range(64)]
    DPAlist = []
    n = len(plainlist)
    for i in range(64):
        hw_std = []
        HWout = sboxout(n, plainlist, i)	#S盒输出
        for i in range(n):
            hw_std.append(HWfun(HWout[i]))	#汉明重量
        DPAlist.append(DPAfun(n, power_std, hw_std))	#正确密钥得到的汉明重量数组被划分成两个集合后的集合均值差
    final_dict = dict(zip(keyList,DPAlist))
    print("正确密钥为:",max(final_dict, key=final_dict.get))	#取最大集合均值差对应的密钥

运行结果我放在了总结里,方便进行对比。具体位置在8.4数据统计中,其中明文数组长度为1000测试结果的截图。

思考问题

对分组密码算法进行DPA攻击时的基本原理

DPA攻击是一种对密码芯片的泄漏功耗 进行统计分析而恢复密钥的攻击方法。DPA攻击的方法是对大量的曲线样点进行功耗统计测试 ,即根据 大量功耗样本来分析密钥的值 ,它具有比简单功耗攻击更高的强度 。

攻击分组密码算法我认为是攻击算法所用的S盒,因为S盒是离散处理数据,像行位移和列变换这种都是线性变换,离散处理的结果不容易观察出规律性。DPA攻击,需要先获取N次密码运算后得到的明文(非密码运算结果),密文,产生的功耗;然后定义一个与密钥密切相关的分割函数J(密文,k)和能量消耗依赖很强的d,猜测子密钥k值,并基于采样时间点,得到两个功耗曲线子集合(d=0和d=1);对功耗曲线进行计算,计算平均功耗值从而得到差分功耗曲线;观察差分功耗曲线,若某个位置出现明细那的尖峰,则表示k猜测正确;猜测正确后根据密码算法的子密钥生成算法逆推密钥。(不同分组密码的子密钥生成算法和密钥位数不同,逆推时穷举搜索次数不同)

总结

猜测正确密钥思路详解

因为DES的S盒运算是“6进4出”的,所以输出的数值化为二进制后所含1的个数范围为0-4。所以猜测密钥处理得到的64个汉明数组的中间值无外乎就0,1,2,3,4五种。但是只有正确密钥处理得到的汉明数组进行DPAfun函数处理后得到的差值最大

为什么集合均值的差值最大就是正确密钥?

猜测密钥汉明重量数组的中间值为2时的分析

2本身作为0-5的中间值,在汉明重量数组内元素基数达到一定程度时数组中间值近乎都是2,我的采用1000长度的明文数组得到的64个汉明重量数组的中间值全是2。集合划分是猜测密钥汉明重量数组内元素值小于等于2,正确密钥汉明重量数组内的元素就要被划分到L集合,剩下的划分到H集合,而影响两个集合的差值的根本原因是部分元素在两个集合中的迁移。

举例进行解析比较方便理解:(ptest数组的中间值为2)

ptsd = [1,2,3,4,4,3,1,2,3,4,3,4,1,2,1,2,……]	 #正确密钥得到的汉明重量数组
ptest = [1,2,3,4,3,4,2,1,1,1,2,2,3,3,4,4,……] #猜测密钥得到的汉明重量数组

将数组划分成五段,方便观看。

0 1 2 3 4 | 4 3 0 0 1 2 | 3 4 3 4 3 4 | 0 1 2 0 1 2 | …………
0 1 2 3 4 | 3 4 1 2 2 1 | 0 0 1 1 2 2 | 3 3 3 4 4 4 | …………

中间值为2的划分规则上面说过了我就不赘述了。我将中间值为2的所有ptsd两集合划分情况进行了遍历举例。

第一段,ptest数组和ptsd数组每一位的对应值都相同,所以不影响划分后集合的均值差;

第二段,ptest数组和ptsd数组虽然每一位的对应值都不同,但是ptsd数组划分后0,1,2都划分到L集合,3,4都划分到H集合,对集合的均值差不影响;

第三段,ptest数组和ptsd数组每一位的对应值都不同,原本应该划分到H集合的4个ptsd数组元素因为对应位置的ptest的值小于等于中间值2,结果被划分到了L集合,这就导致L集合的平均值必然增大,H集合的平均值可能减小,集合均值差减小;

第四段,ptest数组和ptsd数组每一位的对应值都不同,原本应该划分到L集合的4个ptsd数组元素因为对应位置的ptest的值大于中间值2,结果被划分到了H集合,这就导致H集合的平均值必然减小,L集合的平均值可能增大,集合均值差减小;

然后问题又来了,为什么第三、第四段的集合元素划分会导致两个集合的“必然”变化和可能变换呢?

集合均值的“必然”和“可能”变化分析

首先,我们要明确在汉明重量数组的中间值为2的情况下,L集合因为集合内元素的最低值为0、最高值为2,其均值范围为0-2;同理,H集合的均值范围为3-4。

第三段情况如下:

当3,4这种大于原L集合最大均值的数归到L集合中时,会导致L集合的均值必然增大;

失去部分3,4元素的H集合的均值可能变大,变小或不变。

  • 因为3是H集合的最低均值,所以当失去元素3时集合均值会增大或者不变(原H集合全是3)。
  • 因为4是H集合的最高均值,所以当失去元素4时集合均值会减小或者不变(原H集合全是4)。

第四段情况如下:

当0,1,2这种小于原H集合最小均值的数归到H集合中时,会导致H集合的均值必然减小;

失去部分0,1,2元素的L集合的均值可能变大,变小或不变。

  • 因为0是L集合的最低均值,所以当失去元素0时集合均值会增大或者不变(原L集合全是0)。
  • 因为1是L集合的中间均值,所以当失去元素1时
    • 集合均值减小——原L集合均值大于1;
    • 集合均值不变——原L集合均值等于1;
    • 集合均值增大——原L集合均值小于1;
  • 因为2是L集合的最高均值,所以当失去元素2时集合均值会减小或者不变(原L集合全是2)。

综上来看,第三段的情况下必然会导致L集合的必然增大,H集合三种变化可能性都有,集合均值差总体来看是减小的;第四段的情况下必然会导致H集合的必然减小,H集合三种变化可能性都有,集合均值差总体来看是减小的。

注意:

看上面的解释的时候可能会疑惑,比如第三段情况,L集合均值增大,H集合也有可能增大,那为什么不会出现均值增大的情况呢?

这种情况在数组元素基数足够大的时候是不用担心的。当数组长度无限大时,数组内0,1,2,3,4这5个元素出现概率是等概的。就像我们投硬币,掷骰子一样,基数足够大就可以实现。那咱们以这个基础上再去看,拿情况稍微复杂一些的第四段情况举例:在基数足够大的情况下集合内元素全是唯一值的情况几乎是不可能的,所以不考虑均值不变的情况,那L集合均值增大减小的概率是对半开的,但是H集合是必然增大的,则综合来看,集合的均值差必然减小。

小结:

所以只有当ptest数组内的元素和ptsd数组内的元素一一相等时,两集合的均值差才能最大,即猜测密钥猜测到正确密钥时,两集合的均值差才能最大。

第一段或第二段情况可能在ptest数组中存在部分,但是终究会出现第三段或第四段的情况,导致集合差值减小。

猜测密钥汉明重量数组的中间值不为2时的分析

猜测密钥汉明重量数组的中间值为0,1,3,4的情况在汉明重量数组元素基数足够大时几乎不可能出现,不过在这里也把出现这种情况分析一下。

其实原因也很简单,本质上和上面中间值为2时一样。当中间值为0或1时,就表明数组中最少一半的值为0或1,但对应位置的正确密钥汉明重量数组的元素大概率不可能全是0或1,那大于中间值的猜测密钥汉明重量数组对应位置的正确密钥汉明重量数组元素全都被划分到H集合,包括小于3的元素,这就会导致H集合均值的必然减小,L集合均值三种变化皆有可能。这种情况的结论在8.2中已经得出,即集合均值差必然减小。

同理,当中间值为3或4时,就表明数组中最少一半的值为3或4,最终会导致L集合均值的必然增大,L集合均值三种变化皆有可能,集合均值差必然减小。

数据统计

理论说明比较枯燥,也没有数据感受直观,下面我将展示一些我统计到的数据:

测试代码如下,只需要改动主函数即可:

if __name__ == "__main__":
    table = pt.PrettyTable()
    guess = []
    keyList = [i for i in range(64)]
    n = len(plainlist)
    for i in range(64):
        power_std = []
        HWout_true = sboxout(n, plainlist, i)
        for j in range(n):
            power_std.append(HWfun(HWout_true[j]))
        DPAlist = []
        for k in range(64):
            hw_std = []
            HWout = sboxout(n, plainlist, k)
            for m in range(n):
                hw_std.append(HWfun(HWout[m]))
            DPAlist.append(DPAfun(n, power_std, hw_std))
        final_dict = dict(zip(keyList, DPAlist))
        guess.append(max(final_dict, key=final_dict.get))
    table.add_column('使用密钥:', [index for index in keyList])
    table.add_column('猜测密钥:', [index for index in guess])
    print('正确率:{:.2%}'.format(len(set(keyList) & set(guess))/64))
    print(table)

明文数组长度为9的情况下,64次猜测密钥的结果及正确率:

#示例数组:
[41, 35, 62, 4, 33, 44, 22, 46, 18]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
在这里插入图片描述

图8.1     长度9的明文数组测试结果
明文数组长度为1000
的情况下,64次猜测密钥的结果及正确率:
#示例代码
[42, 17, 10, 7, 22, 26, 42, 31, 8, 24, 40, 4, 49, 53, 23, 17, 16, 10, 55, 4, 7, 43, 29, 26, 16, 21, 45, 21, 37, 48, 2, 49, 23, 37, 58, 14, 25, 60, 33, 19, 17, 22, 29, 47, 0, 38, 43, 17, 47, 9, 57, 39, 62, 60, 25, 28, 54, 53, 12, 29, 8, 60, 29, 4, 28, 6, 14, 12, 49, 19, 23, 20, 44, 43, 37, 37, 54, 23, 2, 20, 49, 38, 32, 27, 41, 9, 52, 34, 24, 60, 18, 4, 30, 17, 51, 17, 13, 41, 25, 49, 12, 1, 56, 4, 61, 4, 38, 57, 30, 60, 5, 23, 23, 31, 30, 56, 22, 9, 41, 61, 33, 20, 24, 43, 30, 63, 60, 33, 46, 0, 41, 3, 10, 49, 39, 7, 14, 8, 42, 6, 58, 3, 10, 3, 28, 33, 31, 49, 24, 60, 0, 54, 46, 40, 27, 63, 23, 30, 50, 26, 23, 40, 2, 54, 29, 37, 17, 52, 31, 11, 47, 55, 7, 59, 40, 18, 38, 44, 12, 36, 58, 27, 30, 43, 49, 25, 17, 47, 56, 24, 28, 19, 25, 28, 25, 35, 52, 2, 62, 48, 61, 61, 63, 34, 15, 55, 26, 40, 0, 52, 61, 5, 0, 38, 32, 31, 39, 44, 56, 36, 4, 29, 41, 19, 60, 16, 28, 28, 38, 49, 46, 26, 42, 35, 5, 10, 22, 51, 63, 11, 11, 7, 0, 40, 42, 17, 59, 14, 19, 0, 35, 39, 48, 58, 52, 37, 28, 58, 44, 58, 39, 36, 36, 27, 41, 41, 48, 26, 47, 21, 11, 24, 21, 42, 27, 33, 10, 18, 32, 52, 8, 23, 23, 32, 20, 63, 3, 49, 51, 59, 19, 19, 4, 13, 62, 29, 60, 32, 32, 62, 13, 37, 3, 35, 13, 60, 9, 14, 39, 8, 5, 40, 32, 61, 17, 39, 62, 3, 61, 51, 56, 15, 58, 30, 30, 63, 51, 35, 24, 6, 18, 35, 38, 32, 45, 30, 5, 38, 19, 31, 38, 60, 30, 2, 56, 40, 25, 46, 42, 19, 57, 41, 10, 2, 11, 29, 16, 60, 42, 16, 32, 60, 22, 38, 28, 38, 61, 61, 49, 55, 48, 3, 5, 4, 32, 32, 57, 14, 22, 16, 49, 13, 5, 37, 1, 5, 12, 16, 33, 33, 5, 12, 31, 18, 0, 18, 26, 36, 39, 63, 38, 0, 34, 45, 9, 19, 27, 35, 45, 53, 11, 11, 42, 10, 25, 33, 55, 44, 7, 18, 41, 37, 10, 3, 3, 33, 25, 5, 32, 12, 28, 25, 62, 44, 45, 63, 36, 58, 30, 30, 48, 47, 54, 11, 52, 60, 10, 15, 9, 23, 28, 27, 32, 23, 55, 7, 0, 21, 59, 28, 63, 25, 20, 12, 46, 14, 54, 12, 23, 31, 62, 57, 34, 5, 50, 7, 33, 6, 16, 21, 37, 62, 20, 57, 3, 36, 5, 19, 2, 40, 45, 17, 8, 44, 51, 50, 31, 42, 54, 24, 32, 19, 55, 57, 11, 38, 4, 33, 60, 52, 2, 7, 21, 35, 33, 55, 18, 0, 45, 54, 12, 10, 12, 0, 18, 61, 29, 43, 13, 48, 43, 28, 36, 59, 21, 22, 22, 17, 53, 0, 15, 26, 13, 25, 44, 44, 61, 49, 17, 0, 26, 10, 40, 47, 59, 38, 44, 31, 22, 49, 24, 34, 24, 7, 37, 35, 4, 42, 42, 16, 20, 3, 29, 1, 38, 53, 0, 1, 10, 33, 26, 24, 62, 56, 25, 46, 10, 22, 11, 57, 25, 41, 30, 37, 23, 39, 29, 12, 59, 6, 29, 27, 25, 39, 29, 26, 25, 9, 11, 8, 29, 48, 42, 58, 8, 25, 29, 41, 35, 47, 9, 41, 57, 30, 24, 18, 28, 12, 15, 27, 61, 37, 8, 54, 7, 38, 33, 44, 57, 9, 15, 54, 45, 50, 36, 31, 6, 3, 3, 32, 59, 15, 10, 21, 48, 22, 35, 24, 59, 38, 20, 52, 8, 45, 59, 39, 14, 37, 35, 8, 7, 9, 17, 15, 46, 7, 3, 59, 35, 31, 35, 9, 12, 50, 44, 28, 2, 18, 58, 53, 55, 1, 41, 37, 58, 28, 48, 58, 62, 37, 30, 18, 36, 4, 55, 55, 7, 32, 60, 55, 7, 38, 56, 42, 48, 0, 7, 15, 21, 4, 32, 60, 8, 10, 52, 51, 11, 4, 32, 26, 51, 13, 23, 38, 11, 23, 40, 61, 37, 19, 34, 41, 52, 37, 39, 39, 60, 24, 9, 17, 24, 20, 55, 21, 38, 52, 63, 47, 3, 7, 30, 16, 54, 19, 47, 24, 54, 63, 25, 38, 9, 21, 61, 55, 36, 40, 17, 37, 42, 37, 3, 58, 36, 17, 36, 29, 34, 52, 32, 54, 43, 53, 33, 49, 55, 8, 56, 38, 21, 43, 48, 24, 62, 54, 6, 48, 1, 19, 58, 46, 42, 11, 39, 2, 57, 29, 18, 7, 61, 44, 58, 35, 17, 21, 57, 49, 45, 29, 19, 11, 56, 8, 3, 60, 23, 50, 24, 25, 12, 47, 50, 18, 2, 27, 7, 29, 39, 53, 13, 21, 15, 9, 43, 3, 34, 23, 35, 35, 1, 2, 53, 12, 58, 46, 40, 12, 11, 51, 11, 29, 47, 6, 0, 63, 26, 34, 42, 32, 38, 1, 15, 15, 48, 19, 26, 48, 55, 27, 28, 39, 17, 19, 16, 34, 24, 19, 22, 28, 27, 54, 35, 7, 24, 34, 39, 1, 24, 14, 24, 24, 51, 41, 2, 50, 37, 50, 61, 33, 42, 34, 62, 54, 16, 6, 18, 21, 0, 52, 23, 52, 0, 46, 1, 51, 1, 42, 0, 48, 52, 14, 1, 47, 46, 58, 8, 15, 14, 27, 8, 60, 15, 21, 9, 36, 27, 38, 3, 24, 48, 40, 48, 15, 5, 41, 37, 43, 30, 38, 54, 49, 26, 41, 48, 10, 38, 47, 62, 54, 53, 30, 62, 49, 5, 18, 2, 37, 28, 9, 53, 24, 37, 56, 41, 35, 9, 6, 46, 23, 42, 49]

2-2.5

图8.2     长度1000的明文数组测试结果

为追求严谨,我把长度1000的明文数组也放上了,虽然很占地方,长度9和长度1000这两个数组也是我在此次实验中一直使用的明文数组。

由代码运行结果可知,长度1000的明文数组验证结果是100%的,长度1000的明文数组验证结果是48.44%。明文数组长度越小,其得到的汉明重量数组的中间值和数组内元素分布越不“规范”,猜测密钥结果并不稳定。

我接着测试了10组长度为9的随机明文数组,10组长度为1000的随机明文数组,得到的结果如下:

明文数组长度9:

[35.94%, 59.38%, 43.75%, 65.62%, 50.00%, 51.56%, 70.31%, 43.75%, 35.94%, 56.25%]
平均正确率:51.25%

明文数组长度1000:

[100.00%, 100.00%, 100.00%, 100.00%, 100.00%, 100.00%, 100.00%, 100.00%, 100.00%, 100.00%]
平均正确率:100.00%

小结:

事实胜于雄辩。


校内实验,未完整展示所有代码。若文中有描述错误的地方,欢迎斧正。

  • 12
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值