本章目录(7)On this page (7)
  1. 侧信道在考什么
  2. 四种分析方法
  3. 题目长什么样
  4. 解题:三步
  5. 出题视角
  6. 声学侧信道
  7. 参考
文章Articles

侧信道:从能量轨迹里读比特

一道模板攻击题的完整拆解——欧几里得距离、阈值判断、比特还原。出题和解题是同一件事的两面。

更新Updated 2026.10.25securityctfcryptoside-channel

侧信道在考什么

正常密码学题目,给你密文和算法,让你破解。侧信道题目反过来:算法可能是安全的,但你拿到了运算过程泄露的物理信息。

功耗、时间、电磁辐射、声波、缓存命中率——这些都算侧信道。CTF 里最常见的是功耗轨迹,因为它容易用程序模拟。

四种分析方法

方法 思路 需要什么
SPA 看单条轨迹的形状,直接读操作 对设备内部实现有了解
DPA 多条轨迹做差分统计,从噪声里挖信号 大量轨迹
CPA 建功耗假设模型,算相关系数 功耗模型 + 轨迹
模板攻击 事先建好「0 的轨迹」和「1 的轨迹」,比对相似度 同型号设备 + 模板

CTF 里出得最多的是模板攻击,因为它可以完全用 numpy 造出来,不需要真实硬件。

题目长什么样

给五个附件:

energy_traces_with_flag.npy     # 嵌了 flag 的能量轨迹
energy_traces_with_flag.png     # 同上的可视化
template_trace_0.npy            # 比特 0 的模板
template_trace_1.npy            # 比特 1 的模板

flag 被转成二进制位串,每个位选一条模板,加噪声,拼成一条长轨迹。

解题要做的,就是把这条长轨迹切回一个个比特。

解题:三步

第一步,切分。模板轨迹的长度就是单比特的长度。长轨迹按这个长度等分,得到 N 段。

第二步,判距离。每段分别算到 template_0 和 template_1 的欧几里得距离:

import numpy as np

t0 = np.load('template_trace_0.npy')
t1 = np.load('template_trace_1.npy')
traces = np.load('energy_traces_with_flag.npy')

seg = len(t0)
bits = []
for i in range(0, len(traces), seg):
    chunk = traces[i:i+seg]
    d0 = np.linalg.norm(chunk - t0)
    d1 = np.linalg.norm(chunk - t1)
    bits.append('0' if d0 < d1 else '1')

第三步,转字符。8 位一组,转 ASCII:

flag = ''.join(chr(int(''.join(bits[i:i+8]), 2)) for i in range(0, len(bits), 8))

三步写完不到二十行。这道题的难点不在代码,在于想明白「为什么距离能判比特」——噪声是加性的,模板是固定的,加了噪声的轨迹离原模板最近。

出题视角

自己出这类题,要注意三件事:

噪声别太小。噪声为零,题目变成送分。噪声太大,模板匹配失效。噪声幅度取模板幅度的 10%–20%,既需要判断,又能算出来。

模板别做成常数。如果 template_0 全是 0、template_1 全是 1,那不用算距离,看一眼就知道。模板要有形状,且两条形状要像——像到必须算距离才能分。

提示要给够,但别给答案。给模板文件、给轨迹文件、给一个「怎么转换」的函数骨架,就是不给判断方法。这是 CTF 出题的基本分寸。

声学侧信道

把「功耗」换成「声音」,思路完全一样。

真实世界里的经典案例是:用麦克风录键盘敲击声,做频谱分析,按每个键的声学特征分类,还原输入内容。笔记本风扇转速、CPU 负载引起的主板振动,也能泄露运算强度。

CTF 里的实现通常是给一段音频,让选手做短时傅里叶变换(STFT),看频谱图里的峰值分布,按峰值位置分帧、聚类,映射回字符。

判断顺序和能量轨迹一样:先确定单符号的时间长度,再切分,再比对。

参考

  • 《CTF 密码学之侧信道攻击——声学攻击出题思路》,公众号 攻防SRC
  • 《CTF 密码学之侧信道攻击——声学攻击出题指南》,公众号 攻防SRC