公司动态

RSA功耗分析实战:从波形采集到私钥恢复的完整指南

📅 2026/8/26 5:56:59
RSA功耗分析实战:从波形采集到私钥恢复的完整指南
1. 项目背景与整体思路1.1 为什么又一次研究RSA功耗分析最近我把压箱底的一套RSA功耗分析实验翻了出来重新跑了一遍完整流程。原因很简单这几年关于RSA的功耗分析材料一直在变但很多开源项目年久失修依赖库老掉牙算法实现也停留在十年前的状态。我这次重新做一方面是为了把手头的实验环境梳理干净另一方面是想验证一下当前主流工具链下RSA功耗分析的整个套路到底还能不能顺畅跑通。功耗分析Power Analysis属于侧信道攻击的一种。它不直接攻击数学算法本身而是盯着密码设备运行时的物理泄露——也就是芯片消耗的瞬时功耗。RSA运算里有大量模幂运算运算过程中的中间值会直接影响芯片的电流消耗采集这些电流波形再用统计方法分析就有机会还原出私钥。这个方法从上世纪九十年代末被提出到现在依然是评估密码芯片安全性的关键测试项。我的实验目标很明确在一块普通的微控制器上运行一个不设防的RSA实现用示波器采集功耗轨迹通过简单功耗分析SPA和差分功耗分析DPA尝试恢复密钥最终验证完整的分析链路。整篇文章会按实际执行顺序展开从原理推导、环境搭建、波形采集到数据分析和密钥恢复最后附上我看过的最有价值的几个避坑经验。1.2 这套实验到底能解决什么问题很多人第一次接触功耗分析时都会被一堆术语拦住SPA、DPA、CPA、模板攻击、相关系数、对齐、降噪……看起来门槛很高实际上核心流程非常固定。如果你是一名嵌入式开发者你手里的设备可能跑着基于mbedTLS或OpenSSL的RSA签名逻辑你觉得私钥存在Flash里就安全了。这个实验会告诉你物理世界并不像数学世界那么理想。芯片在计算时不会替你保守秘密功耗波形就是一份完整的手术记录。如果你是安全测试人员这套实验能帮你建立从“拿到一个硬件设备”到“恢复出私钥”的完整方法论。虽然实验环境用的是开发板加示波器和真实攻防场景里的设备不完全一样但分析思路和数学原理是通用的。我给这次实验定的技术路线是不用现成的芯片靶机不用专用的侧信道分析套件就用尽可能普通、便宜的设备完成。这样整套方案的可复现性最强谁都能照着搭起来。实测下来一块常见的开发板加一台入门级示波器再加上一台普通电脑就足够完成基础版的分析了。2. RSA算法与功耗泄露的核心原理2.1 RSA运算中那些容易泄露的环节在正式开始接示波器之前得先把RSA算法本身拿出来拆一拆。RSA的核心操作是模幂运算计算 m^d mod n。其中 d 是私钥n 是公钥模数。私钥的每一个比特都会参与运算而运算步骤之间的功耗差异就是泄露的源头。传统RSA实现使用平方-乘算法Square-and-Multiply从私钥的最高位开始逐位扫描。每一轮迭代都会执行一次平方运算如果当前比特是1还要额外执行一次乘法运算。这意味着私钥里的“1”和“0”对应的运算序列是不同的。观察功耗波形中乘法运算出现的位置就能直接读出密钥的比特序列。这就是SPA的基本思想——不需要任何统计处理肉眼看波形就能还原私钥。更隐蔽的泄露出在乘法运算的内部。即使RSA实现做了指数盲化或者使用了固定窗算法让SPA无法直接区分平方和乘法乘法器在实际计算时处理的数据不同瞬时功耗也不同。1985年发表的Coron攻击、1998年的Kocher DPA论文本质上都是围绕乘法器内部的数据依赖功耗做文章。处理这个中间值的时候如果引入一个猜测的密钥分段计算出中间值的某个比特再和功耗波形做相关性分析相关性最高的猜测值就是正确的密钥分段。还有一类容易忽略的泄露是RSA的 CRT中国剩余定理加速。使用了CRT的RSA实现会把私钥分成 p 和 q 两个因子分别计算最后合并结果。如果CRT合并过程没有做校验攻击者可以通过注入错误诱导设备输出错误签名再用错误签名反推出素数因子。这个攻击不在功耗分析范围内但它提醒我们RSA实现的不同优化手段会引入完全不同的泄露面。2.2 功耗为什么和数据有关如果要给功耗分析找一个物理基础那就是CMOS电路翻转时的动态功耗。一个CMOS反相器在输出从0变为1或者从1变为0时会对负载电容充放电产生一个短暂的电流尖峰。不同的数据值会使电路内部不同数量的节点发生翻转加总的电流消耗就产生了可观测的差异。对于8位或32位的微控制器执行一条指令时内部总线上传输的字节会在多个周期内翻转。处理0x00和0xFF时总线上的变化数量明显不同。处理0x5501010101和0xAA10101010时翻转模式也完全不同。功率波形上显示的毛刺高度和形状实际上是数据值的一种间接编码。需要说明的是单个波形的噪声很大示波器的量化噪声、电源纹波、时钟抖动都会把信号淹没。但功耗泄露是确定性的每次运行同样的操作对应的功耗模式都会重复出现。把多次采集的波形叠加平均随机噪声会逐渐抵消而信号本身会保留下来。这也是为什么DPA需要采集成千上万条波形。还有一个关键概念是汉明重量Hamming Weight。它表示一个字节或一个字里“1”的个数。在大多数CMOS芯片上某个瞬间的功耗和正在处理的数据的汉明重量呈正相关。数据里“1”越多功耗越高。基于汉明重量模型做CPA相关功耗分析是效果最好的攻击方式之一。实验过程中我用过汉明重量模型和比特模型做对比前者的成功率明显更高。2.3 几种主流分析方法的适用场景RSA功耗分析领域的方法论经过多年发展已经比较成体系了这里我把它的演进脉络梳理一下。SPA适用于实现极其简陋的情况比如直接使用Square-and-Multiply且没有做任何掩码波形上能直接看出密钥结构对采集设备要求低、分析速度快但抗干扰能力差稍微加了点防护就失效。DPA基于统计学差异对单条波形的噪声容忍度更高。它对多条波形按某个中间值比特进行分组比较两组的平均功耗曲线。如果某个时刻两组的平均功耗出现显著差异说明该时刻对应操作的中间值和分组依据相关。这个分组的中间值通常选为某个子密钥相关的函数。DPA不需要知道设备的精确功耗模型只要有“大致的功耗差异方向”就能工作。CPA是DPA的改进版它不分组而是直接计算中间值的假设功耗和实际功耗波形之间的皮尔逊相关系数。对于每一个猜测的子密钥会得到一条相关系数曲线最大相关系数对应的猜测就是正确密钥。CPA要预先为每个明文计算中间值并映射为假设功耗值。这里的关键是映射模型的准确性汉明重量模型适用于大多数设备但碰到一些特殊架构芯片可能要换用汉明距离模型。一个常见的误解是必须先做SPA再做DPA实际并不是。SPA和DPA面对的攻击对象不同。SPA针对的是控制流即密钥比特如何控制运算序列DPA针对的是数据流即中间值不同导致的功耗差异。两者可以独立使用也可以组合使用。实验时我已经知道RSA实现是Square-and-Multiply结构所以先做SPA观察密钥结构再用DPA验证某个密钥段的正确性。两条线互相印证结论更可靠。3. 实验环境搭建与功耗采集实操3.1 硬件选型的考量和代价整个实验里最核心的硬件是这三样目标设备、示波器、触发装置。目标设备我选了一款常见的ARM Cortex-M3开发板主频72MHz带有一个简单的LED可以作为触发信号输出。有人问为什么不用STM32F103这种更老的芯片其实都可以但Cortex-M3有现成的RSA加速指令如果不做屏蔽反而会影响功耗特征。我特意在代码里关闭了硬件加速完全用C语言软件实现模幂运算这样功耗特征更明显。示波器是决定实验成败的关键设备。理论上能用一台100MHz带宽、1GSa/s采样率的入门级示波器。实际测试中我手头有一台200MHz带宽的示波器采样率设置为500MSa/s已经足够。功耗分析需要采集整个RSA运算过程的波形一次完整的1024位RSA签名运算大约需要几十毫秒到几百毫秒在这么长的时间里以500MSa/s采样率采集数据会产生大量数据点需要合理控制采集长度。触发装置最简单的方式是使用目标板上的一个GPIO引脚。在RSA运算开始之前把GPIO拉高运算结束后拉低用示波器的上升沿触发开始采集然后采集固定长度的波形。这种方式能保证每次采集的波形起点一致方便后续对齐。还需要一个电流采样电阻或者电流探头。我用的方案是1欧姆的采样电阻串联在开发板的VCC供电回路里用示波器探头测量电阻两端的电压。注意这个电阻不能太大否则会影响开发板的供电稳定性。也有人用磁环加线圈的方式做非侵入式测量效果更好但成本也更高。3.2 目标代码的写入与验证目标设备上的RSA实现不能直接抄OpenSSL因为OpenSSL的代码里做了大量的优化和防护功耗特征不明显。我重新写了一个精简版的RSA模幂运算保留了最容易泄露的结构。伪代码大概是这样的uint32_t montgomery_mult(uint32_t *a, uint32_t *b, uint32_t *n, uint32_t n0_inv) { // 蒙哥马利乘法实现 } void rsa_mod_exp(uint32_t *result, uint32_t *base, uint32_t *exp, uint32_t *mod, int exp_len) { uint32_t temp[64] {0}; uint32_t one[64] {1}; montgomery_mult(temp, one, mod, n0_inv); // 转换为蒙哥马利域 for (int i exp_len - 1; i 0; i--) { montgomery_mult(temp, temp, mod, n0_inv); // 平方操作 if ((exp[i / 32] (i % 32)) 1) { montgomery_mult(temp, temp, base, n0_inv); // 乘法操作 } } montgomery_mult(result, temp, one, mod, n0_inv); // 转回普通域 }烧录前需要检查的一件事是确保编译器没有对模幂函数做自动优化。有些编译器会识别出“无用计算”并直接跳过导致计算时间几乎为零。解决方法是把计算结果写入一个全局变量或者用volatile关键字声明关键变量。我用的是-O0编译选项彻底关闭优化。烧录后先用串口输出做一轮功能验证确保用公钥加密再解密的结果一致确认RSA运算逻辑正确再开始接示波器。这一步不能省我经历过好几次因为代码bug导致波形完全不对的情况排查起来极其痛苦。3.3 示波器采集参数的设置与调整采集参数设置得好不好直接决定后续数据分析的难度。我的经验是先做一个“粗扫”再做“细调”。粗扫目的是看整体波形轮廓。把示波器时基设为每格20ms总采集时间约200ms触发边沿设为上升沿触发源连接的是GPIO触发引脚的通道。按一下开发板上的按键触发一次RSA运算观察波形。第一次看到波形时能明显看到整个运算期间有一个较长的功耗包络中间能看到周期性的起伏。细调的目的是确保单个操作一次平方或乘法的迭代里至少包含几十个采样点。以72MHz主频为例一次蒙哥马利乘法大约需要几百个时钟周期。按每个时钟周期1.0到1.4个采样点来算采样率至少要200MSa/s以上。我设置到500MSa/s这样一条乘法指令的过程里能采集到几百个点足够做后续的相关性分析。每次RSA运算采集一个波形文件为了方便后续处理我直接导出为CSV格式。1000条波形每条波形长度50万个点文件大小大概在几百MB。好在现代电脑内存够用脚本处理起来没有太大压力。采集过程中还有几个容易出错的小地方。示波器探头一定要用短地线长地线会形成天线效应引入大量高频噪声。采样电阻的两端引线要尽量短减小寄生电感。每次采集前要确认电源电压稳定我用的是USB供电没有专门的低噪声电源实测下来噪声在可接受范围内。如果电源噪声太大可以在采样电阻后面加一个大电容滤波但注意加了电容会改变功耗波形的瞬态响应需要重新评估。4. 功耗数据的预处理与对齐操作4.1 为什么对齐是所有分析的前提采集到的原始波形是一维数组但由于触发抖动、时钟精度、程序执行时间变化等原因即使同一个操作在不同次的采集中的相对位置也会有几十纳秒到几微秒的偏差。如果不做对齐直接做平均或者相关性分析信号会被这些时间偏差抹平。对齐算法选择上最简单的方法是找波形中的特征点做平移对齐。比如每条波形开始处的触发沿后的第一个功耗尖峰作为参考点把所有波形都移动到该尖峰对齐。这个方法实现起来容易但对噪声敏感碰到波形质量差的情况容易失败。更稳健的方法是基于互相关的对齐。选一条参考波形把其他波形逐个做平移搜索找到使两个波形间相关性最大的偏移量然后修正。实测下来这个方法在500MSa/s采样率下每条波形大约50万个点互相关运算大概需要几十毫秒1000条波形总共几分钟完全可接受。我在实验中发现直接用循环互相关算法非常快用Python的numpy实现甚至不需要显式写FFT。考虑到时间和效率我最终选择了基于FFT的相位相关方法先计算两条波形的互功率谱再反变换得到相位相关峰峰值位置就是最优偏移。这个方案在带噪声的实测波形上表现很稳定。4.2 降噪、滤波与数据截取对齐之后的波形仍然有大量噪声。主要的噪声来源有几个示波器ADC的量化噪声、开发板电源纹波、电磁干扰。降噪策略取决于后续要做什么分析。SPA主要靠肉眼识别所以要做平滑滤波。DPA/CPA虽然有统计平均来抵消噪声但滤波仍然能提升信噪比。我用的降噪方案是先做一个简单的移动平均滤波窗口大小选5个采样点。这个窗口在500MSa/s采样率下对应10ns不会抹掉运算细节但能明显降低高频毛刺。如果是DPA分析我会省掉移动平均直接做相关分析让统计学方法自己去“平均”。数据截取这一步很多人不注意。RSA运算的整个波形里真正关心的是平方和乘法运算的那一段时间。如果把前后空闲期的波形也纳入分析不仅增加计算量还容易引入无关的相关峰。我的做法是根据触发信号确定起点再根据已知的RSA运算时长截取中间的有效区间。对于1024位密钥指数长度为1024位Square-and-Multiply的迭代次数约为2048次。通过观察波形中的周期性特征来确定单次迭代的长度再乘以迭代次数就能估算出有效区间。我截取了一个从第一个平方运算开始到最后一个乘法运算结束的区间。这段数据大约占整个波形的80%完全覆盖了私钥处理过程。4.3 波形质量评估与重采把波形处理到这一步之后不要急着做分析先做一轮质量检查。检查内容包括波形幅度是否在预期范围内不要出现ADC饱和波形是否出现整体漂移可能由于供电不稳定对齐之后波形之间的残差是否正常。质量检查还有一个量化指标就是信噪比的计算。选取一段无运算的安静区计算噪声标准差再选取一段有明显运算活动的区域计算信号标准差两者比值作为信噪比参考。如果信噪比低于某个阈值我会重新检查示波器探头接地和采样率设置。我实测过程中遇到过一次非常蹊跷的现象采样率设置为1GSa/s时波形反而比500MSa/s更差。后来发现是示波器的带宽限制设置导致的。很多入门级示波器在1GSa/s采样率下会启用20MHz带宽限制反而滤掉了关键的功耗尖峰。关掉带宽限制之后波形质量立刻恢复正常。这提醒我在设置采样率时要同步检查带宽设置不同示波器的具体配置差异很大。5. 实战SPA与DPA/CPA恢复密钥5.1 简单功耗分析SPA直接读取密钥当波形预处理完毕SPA是整个实验中最直观、最有成就感的一步。把对齐后的波形画出来横轴时间纵轴电压肉眼观察波形的“纹理”。在Square-and-Multiply算法里每轮迭代包含一个平方操作如果当前密钥比特为1同一个迭代周期内会出现一个额外的乘法操作。而平方和乘法虽然都是大数乘法但操作数不同在功耗波形上会有细微差别。在理想情况下每一轮迭代对应一个固定长度的波形段内部有一条或两条“功耗高峰”。对比波形的周期性结构能直接读出密钥序列。我的实际经验是纯肉眼观察能分辨出大部分密钥比特但遇到某些“1”和“0”之间差异极小的位置需要放大波形仔细对比或者用频谱分析辅助判断。SPA的局限在于实现稍加防范就失效。比如使用固定窗口算法每轮迭代的乘法次数固定密钥被窗口内的索引值分散编码肉眼就无法直接读取了。但SPA依然是功耗分析入门最好的练习因为它建立了一个直觉运算序列和功耗波形之间有清晰对应关系。我在实验里用SPA成功还原了完整的128位实验密钥。为了验证准确率我把实际密钥和SPA读出的结果逐比特比对100%一致。这个结果不出意外因为目标设备上跑的是完全没有防护的实现典型的教科书级示例。5.2 差分功耗分析DPA的完整推导SPA的成功让我对数据质量有了信心但真正的重头戏是DPA。DPA的目标不是读取密钥结构而是通过统计方法验证某个密钥分段是否猜测正确。我用一个具体例子说明DPA的推导过程。假设RSA实现里的模乘运算使用了一个可预测的中间值比如某个乘法结果的最低有效字节。对于每一条采集到的波形计算该中间值根据中间值的比特值分为两组一组是比特为0一组是比特为1。然后分别计算两组波形的平均电平均值用两条平均曲线做逐点相减得到差分曲线。如果猜测的密钥分段是正确的那么分组依据和实际设备内部操作一致在中间值被计算的那一个时间窗口附近差分曲线会有一个明显的尖峰。如果猜测错误分组杂乱无章差分曲线基本平坦。但要注意DPA的差分曲线即使正确时峰值位置也可能出现在多个点因为一个中间值会影响后续多个操作的功耗。更实用的是CPA方案。CPA不是简单地分成两类而是为每个明文计算假设功耗值比如汉明重量然后计算所有明文下该假设功耗与实测波形每个时间点的相关性。在正确猜测和正确时间点处会看到一个明显的相关系数峰值。相比DPA的差分幅度CPA的相关系数提供了更明确的统计指标。5.3 分而治之分段恢复RSA私钥的完整方案我的RSA私钥是1024位直接穷举攻击不现实。但RSA模幂运算是按词32位或64位处理的每次运算通常只处理一个或两个完整词的数据。这意味着攻击可以按词分段进行。以32位单片机为例模幂运算里的蒙哥马利乘法通常按32位一组处理中间值的某些特征可以通过单个32位词计算。攻击者可以对每一段比如私钥的最低32位做穷举每个32位猜测产生一个中间值计算相关系数最高相关系数的猜测即为该段密钥。每段32位共32段1024位逐段恢复就得到了完整私钥。分段攻击里有一个重要的实现细节分段间的依赖关系。如果两个分段在运算时同时参与某个操作比如进位传播那么直接独立攻击可能失败。解决方案是先恢复低32位再把已恢复的密钥段作为已知量参与高32位的中间值计算。这种逐段迭代的方式类似拼图时先拼出轮廓再填充内部。我在实验中使用CPA每段32位密钥恢复精度达到了100%。需要指出的是由于我的实验密钥长度只有128位为了缩短采集时间分段只有4段攻击速度飞快。如果换成真正的1024位私钥每一段依然只需计算2^32次猜测约40亿次在GPU上用并行计算几个小时就能完成完全在可行范围内。5.4 分析脚本的框架设计实验中的数据分析脚本我用Python编写核心依赖是numpy和scipy。整体框架分为数据加载、对齐、模型计算、相关性分析和结果可视化五部分。主循环的简化伪代码如下import numpy as np from scipy.signal import correlate import os traces [] keys_guess [] # 加载所有波形 for fname in os.listdir(./traces): trace np.loadtxt(fname, delimiter,, skiprows1) traces.append(trace) traces np.array(traces) # shape: (num_traces, num_points) # 对齐以第一条为参考 ref traces[0] aligned [] for trace in traces: corr correlate(trace, ref, modefull) lag np.argmax(corr) - (len(trace) - 1) aligned.append(np.roll(trace, -lag)) traces np.array(aligned) # 逐段猜测 for guess in range(0, 2**32): intermediate compute_intermediate(plaintext, guess) hyp_power hamming_weight(intermediate) # 计算每个时间点的相关系数 corr_coeff np.array([ np.corrcoef(hyp_power, traces[:, t])[0, 1] for t in range(traces.shape[1]) ]) max_corr np.max(np.abs(corr_coeff)) if max_corr best_corr: best_corr max_corr best_guess guess这个脚本直接跑的话会很慢因为2^32次猜测里每一次都要对每个时间点算相关系数。实际优化时我把所有时间点的数据组织成矩阵利用numpy的向量化一次处理。更高效的方案是把波形按关键时间窗口截短只保留中间值被计算的100个采样点这样计算量减少5000倍。我在实际代码中用了并行处理把2^32次猜测分到多个CPU核心上跑每个核心处理自己的一个分段。在16核心的机器上每段恢复时间缩短到几分钟。对于完整RSA密钥的恢复这个方法可以平滑扩展到GPU。6. 常见问题与排查技巧实录6.1 波形看起来全是噪声找不到运算区这是最常遇到的问题。第一次接好示波器时波形可能看起来毛刺很多完全找不到规律的运算区。排查思路是先确认触发是否正常工作。如果触发沿没有设置对示波器可能采集了空白区域看起来当然没有信号。另一个常见原因是GPIO触发信号的位置不对。触发信号要在RSA运算开始时精确拉高如果触发提前或延后波形会有一部分被截掉或者包含大量无用的空闲期。解决办法是在代码里用逻辑分析仪确认GPIO翻转和模幂运算开始的时序关系必要时调整GPIO控制代码。还有一种情况是采样率太低。如果设置成10MSa/s一条完整的RSA运算只对应几百个采样点波形上看不到任何结构。把采样率调到200MSa/s以上再看一般就能看到清晰的包络。6.2 对齐之后波形依然有大量残留误差波形对齐并不是完美无缺的。即使做了互相关对齐不同波形的同一操作之间仍然可能存在细微的时序偏差。这种偏差可能来自芯片内部时钟的微小漂移也可能来自供电电压变化导致指令周期变化。如果对齐后残差依然很大可以尝试更精细的对齐策略。比如把波形分段每一段独立对齐而不是整条波形只做一个全局位移。但分段对齐要小心如果某一段里本来就没有明显的特征点对齐反而可能引入更大误差。我实际用过的一种方案是逐点动态时间规整DTW效果很好但计算量大。对于大规模实验这个方案有些奢侈通常只在波形数量较少时使用。大多数场景下基于相位相关的全局对齐已经足够支撑后续分析。6.3 DPA/CPA相关系数不到0.03怎么办相关系数低通常不代表攻击失败而代表信号太弱或者模型不匹配。首先检查选择的中间值模型是否正确。汉明重量模型假设功耗和数据中“1”的数量成正比但有些芯片的功耗更依赖于数据翻转次数汉明距离模型。换用不同的功耗模型常常能明显提高相关系数。其次检查采样点选择。如果中间值计算的时刻对应的功耗波形点被误判相关系数自然很低。用可变时间来选择目标点而不是固定某一个时间点可以提高攻击成功率。时间可变性让攻击者可以在所有时间点中搜索最高的相关系数出现的位置然后再确认。最后检查波形数量。如果只采了100条波形统计噪声太大。我建议至少采集1000条如果功耗泄露较弱增加到5000到10000条会更稳健。波形数量每增加十倍相关系数的标准误差就缩小约三倍更容易出现明显的峰值。6.4 设备厂家会用哪些反制措施有些读者在做自己设备的功耗分析时可能会碰到攻击失败的情况。这时候大概率不是你的分析能力有问题而是目标设备做了防护。最常见的是掩码防护。指数盲化Exponent Blinding让每次运算时私钥都乘以一个随机数导致波形每一轮处理的数据都不同SPA无法直接读取密钥。消息盲化Message Blinding给输入数据加随机数DPA的中间值计算彻底失效。这两招都能有效防御传统功耗分析也是目前绝大多数商业密码库的默认配置。针对掩码防护攻击者需要用到高阶DPA或者模板攻击。高阶DPA试图分析多时刻功耗的联合分布来绕过掩码计算复杂度高且单条波形的噪声被放大。模板攻击则需要攻击者先有一台同型号的参考设备在可控条件下建立功耗特征模板。这两种方法对设备要求更高但依然是评估高安全级芯片时必须考虑的攻击方式。我在实验中没有实际攻破这些防护措施但把它们的原理和应对思路理了一遍。当你面对一个加了掩码的RSA实现时首先要确认掩码是在算法哪一层加的是消息盲化还是指数盲化这决定了后续攻击要打哪个点。6.5 实验中的十个高频踩坑点编译器优化了你的演示代码用-O0保留所有计算别偷懒。触发信号提前或滞后用逻辑分析仪实际测量GPIO翻转时序。示波器带宽限制未关闭某些示波器默认开启20MHz低通必须手动关闭。探头地线夹太长地线长度尽量小于2cm否则会引入50Hz工频干扰。采样率虚高但有效位不足500MSa/s采样率下实际有效位数可能只有6-8bit。检查示波器指标必要时用多次采集平均来提升动态范围。波形文件过大导致内存不足先截取感兴趣的时间区间再保存别一条波形存几百万个点。数据对齐的参考点选择错误参考波形要选一条信号最强、噪声最小的而不是第一条。中间值计算公式错误仔细检查RSA实现里的字节序和位序大端和小端混淆会让CPA完全失效。相关性只算一次不够多条波形分批次做CPA确认峰值稳定出现而不是偶然噪声产生的尖峰。忘了做随机化验证换一组完全不同的随机明文重新采集如果依然恢复同一个密钥段说明结果可信。这些坑每个我都在实验里踩过至少一次每次排查都要花上几个小时。写在这里希望能帮你少走一些弯路。7. 实验扩展方向与个人经验总结7.1 从实验板到真实场景的距离如果你完整跑通了我上面描述的流程你可能会问这套方法是不是可以用来攻击真实设备答案要谨慎。真实设备上的密码芯片通常有不同程度的防护有的在硬件层面加入了功耗随机化电路有的在协议层面做了非对称操作时序混淆还有的干脆把所有敏感运算都放到安全岛里执行。相应地真实攻击场景对设备、环境和经验的要求都会急剧上升。但在嵌入式固件安全测试中功耗分析确实已经成为一项标准检查项。不光是RSAAES的功耗分析也是热门方向。不少安全认证标准如CC、FIPS都明确要求对密码模块进行侧信道泄露评估。如果你写的是跑在裸机上的密码库实现功耗分析测试应该加入你的自测清单。我这次实验用的是老式Square-and-Multiply实现可以说是最脆弱的目标。但正因如此它完美展示了功耗分析的核心思想任何物理计算过程都会留下痕迹而数学上的安全与物理上的安全完全是两回事。7.2 我踩过最深的坑与最后的建议这次实验踩过最深的一个坑发生在采集环节。我最初用了一根很长的探头地线夹波形上叠加了明显的50Hz工频信号但当时我以为那是正常的电源纹波没在意。后续做DPA时所有波形的相关性都被这个工频分量污染导致攻击失败。最后换了短地线夹重新采集了一轮问题立刻就消失了。硬件细节对功耗分析结果的影响远远超过很多初学者的想象。对准备入门功耗分析的朋友我建议从最简单的实验开始用SPA去识别一个明文没有掩码的AES-128的密钥。AES的轮运算结构规整密钥扩展过程清晰比RSA更适合作为第一个实验。跑通之后再切换到RSA的模幂分析你会更容易理解两种算法的功耗特征差异。工具方面除了自己写脚本也可以关注ChipWhisperer和CWAnalyzer这类开源硬件和分析软件。ChipWhisperer提供了从目标板到采集设备的一体化方案在入门期能节省大量折腾时间。但要注意用现成工具的同时最好能理解背后的算法和统计学原理否则换个平台或换个目标芯片你可能又不知道该怎么把问题拆解开了。功耗分析是一个需要耐心和细心的领域。我把这次实验的完整过程写出来最希望读者获得的不是某条命令行或者某个脚本而是建立一种思维习惯当你在设计或评估一个密码系统时不仅要考虑算法本身的安全性还要把它的物理实现方式也纳入安全边界内。从数学攻击到物理攻击攻防的战场正在不断延伸。对每个做嵌入式安全或密码学相关工作的人来说亲眼看到功耗波形暴露密钥的那一刻你才真正理解为什么“侧信道”三个字在安全圈里始终拥有特殊的地位。