作者:backahasten
稿费:350RMB
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
前言
最近在做老师留的翻译作业的时候。发现了很多有关于侧信道攻击的文章。目前,在国内的安全圈子中很少看到与侧信道有关的内容,希望这篇可以做一个补充。
我先挖个坑,希望会写3篇,这是第一篇,差分能量攻击(DPA),第二篇可能是cache攻击,第三篇TEMPEST攻击,我希望我会写完。
学习一项技能最好的办法就是亲手操作一下,斯普林格出版社出版的侧信道攻击年刊里的一篇文章,作者使用DPA攻击了一个没有设防的IC卡,并且给出了完整的数据集;www.dpabook.org 上也有可有完整的能量轨迹和matlab代码示例,这样就给了我们动手练习的基础,我也加入了其他我读到的一些内容,这篇文章是我的一个总结,如果有错误,希望各位前辈提醒指正。
I.背景知识
芯片在运行的时候,由于数据或者逻辑的不同,内部的晶体管通断是有区别的,通过这个区别来确定程序内部的数据或者指令,就是侧信道攻击。获取这个区别有很多方法,比如在芯片的GND引脚处获取电压,通过探针去截取芯片辐射的变化等等。
我们的身边有很多密码学设备,比如大家的银行卡,门禁卡手机卡等等,侧信道攻击原来主要是针对这些设备的,可是随着人们对侧信道攻击的重视,密码学设备都增加了对侧信道攻击的防护,(当然,有一些没有防护),侧信道攻击和信息安全的其他技术一样,都是一个动态发展的过程。
侧信道攻击近几年也在智能硬件的攻击上被使用,比如2016年,就有人使用SPA(另一种侧信道攻击方法)攻击了一个智能保险箱。总之,侧信道攻击对于运算单一,时钟频率低(时钟频率低这点很重要)的设备中的加密攻击是很有效的。
在本文的第二部分,我会简单介绍一下攻击的流程,给大家建立起一个思维架构;第三部分,我会先使用网站上和书中的能量轨迹结合攻击的使用的算法开展一个真实的攻击,第四部分,我会说一些多样话的攻击方法和能量轨迹的获取。最后,我会给大家推荐一些有关于这个方面的书和文档。ps:怎么有写论文的感觉。
II.攻击流程
针对与所有的侧信道攻击(包括DPA,TEMPSET,cache泄露等)主要就是两个思路,第一个就是侧信道泄露的截取,第二个是信息的恢复。本节我会主要介绍这两点(只针对这种小设备中的密码学攻击的情况)。
1.信息的截取
设备上,示波器是必须的,无论如何,示波器一定要有把数据传输给电脑的能力,因为之后的处理都是使用matlab进行的。根据《能量分析攻击》这本书中的介绍,针对芯片,主要有以下几种获取泄露的方法。
在GND引脚处串联一个小电阻,大概是1~50欧姆,之后使用示波器测量电阻上的电压。
使用电场探针或者磁场探针获取芯片的电磁泄露。
还有很多其他的方法,比如什么表面扫面法,工作台法拉第笼法等等,这还是要根据具体情况去具体分析。在这里,我们将使用《能量分析攻击》这本书里配套的能量轨迹,这个训练集是使用小电阻耦合得到的。
2.信息的恢复
这种类型的侧信道攻击,主要有简单能量分析攻击,差分能量分析攻击等。
简单能量分析攻击:
简单一点说,就是把能量轨迹显示出来之后用眼睛“看”,当然,也有很多辅助看的方法,比如模板碰撞。SPA的有点是需要的能量轨迹少,缺点是需要泄露比较明显,对噪音的敏感性大。这不是我们的重点,就不说了,有兴趣的师傅可以看我后面推荐的书。ps:主要是我不太熟悉,逃。。。。
差分能量攻击:
和模板类似,我们要使用已知的明文或者密文对加密算法的一个步骤进行匹配。可以说成只针对一个步骤的密钥的爆破。DPA的优点是,即使泄露较小,也可以有效识别,有天然的对噪音的过滤,缺点是需要的能量轨迹很多。
DPA的基本想法就是,通过大量的能量轨迹计算能量轨迹和数据的依赖性。
获取能量轨迹:
首先,我们要确定一个中间值f(d,k),这个f一般是密码学算法的一个中间值,d必须是已知的,我们整个DPA的目的就是求k,k可能是密钥的一部分,或者密钥派生出来的值。接下来,使用示波器去接受对应的能量轨迹。完成之后我们有两个矩阵,第一个矩阵是一个只有一列的矩阵(或许应该叫向量),内容是我们已知的或者是可控的d值,长度是len(d),我们叫他大D。第二个矩阵T是一个len(d)*T的矩阵,T是采样的点数,也就是能量轨迹的长度。每一个d对应矩阵C的一行。这里牵扯到能量轨迹对齐的问题,我们会在第四节讨论这个问题。
计算假设的中间值:
接下来,我们需要一个向量大K,大K应该包含所有小k,即遍历所有k的密钥空间。之后,使用矩阵D和矩阵大K生成矩阵V,使用如下的伪代码进行解释。
for i = 1:1:len(D)
for n = 1:1:len(K)
V(i,n) = f(D[i],K[n]);
end
end
这样,我们就得到了矩阵V,矩阵V的每一行是已知值d相同,密钥K不同,每一列是密钥值k相同,已知值不同。
生成能量模型:
这一步,我们使用上文的V矩阵生成一个对应的矩阵H,矩阵H的名字叫假设能量消耗模型,其中的值就是我们假设的能量消耗值。
有很多方法去获得这个能量的消耗值,比如使用器件级别甚至晶体管级别的仿真,可是这样就需要对芯片的结构有很深的了解,牵扯到了“芯片逆向”这门武林绝学。实际上,有很多简易的方法可以做到同样的效果。比如汉明距离和汉明重量。
看一串二进制:00111010,10001110,汉明距离是两个二进制数中,0到1或者1到0的转换的个数,在这里,就是4,因为第1,3,4,6位有转换。汉明重量是二进制数中1的个数,这两个二进制数的汉明重量都是4。
同样的,还有很多方法可以,我们会在第四节继续讨论。
比较两个能量轨迹
这个比较有很多种模型和方法,我们只说一种最常用的,基于相关系数的攻击。在这一步,我们参与运算的矩阵是测量的矩阵C和我们生成能量的模型V。计算方法如下。
[d1,k] = size(H);
[d2,t] = size(T);
for i = 1:1:k
for j = 1:1:t
ans = corrcoef(H(:,i),T(:,j));
R(i,j) = ans(1,2);
end
end
之后,我们就可以得到相关系数矩阵R,每一行代表真实的密钥值和我们假设的密钥值的相关系数,最大的哪条,就是我们要找的密钥值,对应的T时刻,就是这一步中间函数执行的时刻。
III.演示实例
我们先来回忆一下数学符号的问题:
f(d,k)函数:这是密码学计算的一个中间步骤,d是我们已知的明文或者密文,k是我们要获取的部分密钥。
D,一个向量,里面储存着我们已知的明文或者密文d。
K,一个向量,遍历所有可能的密钥值k。
T,一个矩阵,每一行是随时间变化而变化的能量值,行数是已知的明文或密文d的数量。
V,一个矩阵,是使用f函数计算了所有可能D,K之后的值。
H,把矩阵V的每一位使用生成能量模型计算之后的值,大小与V相同。
我使用网站上的能量轨迹进行测试,它包含了3个能量轨迹,ws1-3,我使用最一般化的ws3能量轨迹。
什么叫最一般化呢,就是实际情况中,攻击者可以相对轻松获取的轨迹。比如,获取到的能量轨迹是失调的。失调的原因可能是在获取矩阵T的时候,本来要求的是所有的采样点数应该是与芯片内部执行的时间对齐的,可是这在现实中是不太可能完全对齐的,因为这需要很小心的去设置示波器的触发。或者是芯片使用了乱序操作来对侧信道进行防御。
我先直接给出他的代码和运行之后的结果,并使用注释对代码进行解释。
load('WS3.mat');
%{
aes_plaintexts: 可知的输入值,也就是矩阵D,这里大小是1000*16,也就是有16次不同的输入,我们这里只对第一次进行攻击
traces_noDummy: 能量轨迹,没有插入随机指令作为防护,1000*25000也就是矩阵T
traces_withDummy: 能量轨迹,插入了随机指令作为侧信道攻击防护,1000*25000也就是矩阵T
HW: 用来储存汉明重量,便于后面调用
%}
samples = 1000;
%选择是否进行了随机插值的能量轨迹,下文会进行对比
analyzed_traces = 'traces_noDummy';
%analyzed_traces = 'traces_withDummy';
%选择哪条能量轨迹进行攻击,一共有16条
byte_to_attack = 1;
more off
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 读取存储空间中aes_plaintexts的第一列
D = aes_plaintexts(1:samples, byte_to_attack);
clear aes_plaintexts byte_to_attack
% 选择能量轨迹
eval(sprintf('traces = %s(1:samples, :);', analyzed_traces));
clear analyzed_traces
%密钥有256种可能,K的空间是256
K = uint8(0:255);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% TASK 2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 计算中间值,这个就是上文中的f(d,k),这个函数的选取就是我们需要攻击的函数,计算之后是矩阵V
V = SubBytes(bitxor(repmat(D, 1, length(K)), repmat(K, samples, 1)) + 1);
% 使用汉明重量计算假设能量值,计算之后是矩阵H
H = HW(V+1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 计算相关性
tr_length = size(traces, 2);
R = zeros(length(K), tr_length);
for key_idx = uint16(K)+1
fprintf('Working on key guess = %dn', K(key_idx));
%下面计算相关系数矩阵
for k = 1:tr_length
r = corrcoef( [double(H(:,key_idx)) double(traces(:,k))] );
R(key_idx, k) = r(1, 2);
end
end
clear key_idx k r
%下面我改了一些,有助于快速定位攻击成功的位置
[b,c]=max(max(R')); % c的值就是对应的正确密钥值
plot(R(c,:));
我们看下攻击的结果(运行时间比较长)。下面是TASK 2运行之后,正确密钥0x10的图。图3_1
相比于不正确的密钥,相差很大。图3_2
对于没有进行很好对对齐的能量轨迹(matlab脚本中选择analyzed_traces = 'traces_withDummy';),也有明显的相关性峰值,只不过最大值会缩小。图3_3
IV.尾声
1.优化
我们先来考虑一下,有什么可以优化的。
所以先要来考虑,为什么要优化。
优化,就是为了可以使用更少的能量轨迹,去攻击泄露更不明显的能量轨迹。或者是绕过一些防御手段,比如掩码防护,或者针对不知到计算细节的特殊加密方案的攻击,等等。
我们再来看一看,有什么地方值得优化,比如生成假设能量模型和对比假设能量模型和实际能量模型,可以使用不同的模型使得获取到的假设模型和比较结果更优化。我们的示例只针对了一个中间量来进行计算,那么对于使用了掩码的能量轨迹,我们可以使用几个中间量进行高阶DPA攻击。对于不知道具体计算过程的算法,可以使用旁路立方体攻击,等等。需要优化的地方还很多。
2.能量轨迹的获取
这是个很重要的问题,我没有单独拿出一章来讲的原因是我没有实际操作过,主要是因为没钱买适合的示波器。我会简单的介绍一下。
在2017年斯普林格出版的 Hardware Security and Trust 年刊第四篇 Practical Session: Differential Power Analysis for Beginners中,介绍了作者获取IC卡能量轨迹的方法,具有很强的通用性,可以借鉴一下。待我有钱买示波器之后,我也会自己动手做一遍。
diy一个板子,引出IC卡的接触引脚,如图4_1
之后按如下的方法接线,一路测量数据,另外一路测量功率图4_2
使用JSmartCard Explorer通过一个读卡器与接触式IC卡进行交互,使用 PicoScope 6 GUI读取能量轨迹。4.4
图4_3
V.参考
《能量分析攻击》(奥地利)Stefan Mangard、Elisabeth Oswald、Thomas Popp,冯登国,周永彬,刘继业 译 科学出版社。以及配套网站,www.dpabook.org(入门好书)
《密码旁路分析原理与方法》郭世泽 王韬 赵新杰 科学出版社 (进阶必备)
N本斯普林格出版社(springer)年刊 Constructive Side-Channel Analysis and Secure Design
N本斯普林格出版社年刊 Hardware Security and Trust
文件下载
链接:https://pan.baidu.com/s/1hrSJkf6 密码:qgh8