uzairashfaq85/-Side-Channel-Analysis-on-AES-128

GitHub: uzairashfaq85/-Side-Channel-Analysis-on-AES-128

针对STM32微控制器AES-128实现的相关性功耗分析攻击项目,包含硬件改造、功耗采集、多模型统计分析与密钥恢复完整流程。

Stars: 0 | Forks: 0

# AES-128 侧信道分析 ![Project Banner](https://placehold.co/1200x320?text=Side+Channel+Analysis+on+AES-128) 针对运行在 STM32 Nucleo 微控制器上的硬件 AES-128 实现的一次实践性**相关性功耗分析 (CPA)** 攻击。通过捕获加密过程中的功耗轨迹,我们利用统计泄漏模型恢复了完整的 128 位密钥。 ## 目录 1. [项目概述](#project-overview) 2. [硬件设置与修改](#hardware-setup--modification) 3. [攻击方法论](#attack-methodology) 4. [仓库结构](#repository-structure) 5. [任务 1 — Python CPA 攻击](#task-1--python-cpa-attack) 6. [任务 2 — MATLAB 功耗模型对比](#task-2--matlab-power-model-comparison) 7. [Jupyter Notebook (Scared)](#jupyter-notebook-scared) 8. [结果](#results) 9. [技术栈](#tech-stack) 10. [设置与使用](#setup--usage) ## 项目概述 侧信道攻击利用无意的物理信息泄漏(功耗、电磁辐射、时间),而不是攻击密码算法的数学结构。本项目对 AES-128 执行了一次 **CPA 攻击**: - 目标设备 (STM32 Nucleo) 加密随机明文块,同时我们用示波器记录其瞬时功耗。 - 对于 16 个密钥字节中的每一个,我们测试所有 256 种可能的假设,对预期的功耗进行建模(使用 `SubBytes(plaintext ⊕ key_guess)` 的汉明重量),并找出其建模功耗与真实轨迹相关性最强的假设。 - 正确的密钥假设会产生一个尖锐的相关性峰值;而所有其他假设则保持在零附近。 ## 硬件设置与修改 为了最大化信噪比 (SNR),STM32 Nucleo 开发板进行了物理修改: | 修改 | 目的 | |---|---| | 在 VDD 电源线上插入**分流电阻** | 将电流消耗转换为可测量的电压 | | 从电源轨移除**去耦电容** | 防止信号平滑,暴露高频功耗尖峰 | | 在 AES 固件中添加 **GPIO 触发** | 将示波器捕获同步到加密开始的精确时刻 | 功耗轨迹是使用低噪声示波器探头捕获的。每条轨迹覆盖 AES 第一轮的完整过程(1 000 个样本)。为了攻击,收集了一个包含 **10 000 条轨迹** 及其对应明文的数据集。 ## 攻击方法论 ``` PC --[UART]--> STM32 Nucleo | (AES-128 encryption + GPIO trigger) Oscilloscope --> power_trace.bin PC --> plaintext.bin ``` ### CPA 工作流程 1. **数据收集** - PC 通过 UART 发送随机的 128 位明文。 - 示波器从 GPIO 触发点开始捕获功耗轨迹。 - 数据集:10 000 条轨迹 × 1 000 个样本,存储为 `double` 精度二进制。 2. **泄漏建模** - **目标:** 第一轮 `SubBytes` 输出 — `V = SubBytes(P ⊕ K)`。 - **模型:** 汉明重量 (HW) — 假设功耗与 `V` 中置位位的数量成正比。 - 对于 16 个密钥字节中的每一个,生成 256 个功耗假设:`H[k] = HW(SubBytes(P ⊕ k))`。 3. **统计分析** - 计算 `H[k]` 与轨迹矩阵的每个样本列之间的皮尔逊相关系数。 - 具有最高绝对相关性的密钥字节假设即为恢复出的密钥字节。 - 对所有 16 个字节独立重复攻击。 4. **功耗模型对比** (任务 2) - MATLAB 脚本额外评估了 **8 种单位泄漏模型**(位 0 到 位 7)以及汉明重量模型。 - 针对每种模型测量成功恢复所需的最小轨迹数量。 ## 仓库结构 ``` . ├── README.md ├── .gitignore ├── Task1_Python_Code_Files/ │ ├── AES_CPA_Scared.ipynb # End-to-end CPA attack using the Scared library │ ├── CPA_Attack_Simple.py # Modular, fully vectorised CPA attack (main script) │ ├── cpa_attack.py # Alternative implementation (struct-based loader) │ ├── data/ # [gitignored] Binary input datasets │ │ ├── datapoints.bin # Raw power traces (10 000 × 1 000 samples) │ │ ├── plaintexts_SCA.bin # Corresponding 128-bit plaintexts │ │ ├── HW.bin # Hamming Weight lookup table │ │ └── SubBytes.bin # AES SubBytes lookup table │ └── plots/ # [gitignored] Generated correlation plots │ ├── CPA_attack_full_key.png │ └── Tiny_AES_CPA_attack_full_key.png └── Task2_MATLAB_Code_Files/ ├── lab_task2_123.m # CPA attack + 9-model comparison in MATLAB ├── attack_data_10k.mat # [gitignored] 10 000 captured power traces ├── constants.mat # [gitignored] SubBytes table and HW lookup ├── dpa_attack_results.mat # [gitignored] Saved attack results └── matlab_code.mat # [gitignored] Auxiliary MATLAB data ``` ## 任务 1 — Python CPA 攻击 提供了两个 Python 脚本,它们以略有不同的代码组织实现了相同的攻击。 ### `CPA_Attack_Simple.py` (推荐) 一个清晰、完全模块化的实现: | 函数 | 描述 | |---|---| | `load_plaintexts()` | 加载并将明文二进制文件重塑为 `(N, 16)` | | `load_traces_transposed()` | 加载轨迹二进制文件,将按列存储转置为 `(N, 1000)` | | `compute_hamming_weight_table()` | 构建 256 项 HW 查找表 | | `cpa_recover_key_byte()` | 针对一个密钥字节的向量化相关计算 — 返回最佳猜测 + 256 个相关值 | | `recover_full_aes_key()` | 遍历所有 16 个字节,返回完整密钥 + 配置文件 | | `plot_key_correlations()` | 将 4×4 网格的相关性条形图保存为 PNG | 正确密钥以**红色**突出显示;所有其他假设为浅蓝色。 ### cpa_attack.py 一个使用 `struct.unpack` 加载轨迹的等效实现。核心相关计算是相同的。该脚本还提供了一个 `plot_single_byte()` 辅助函数,用于快速检查单个字节。 ### 运行 ``` cd Task1_Python_Code_Files # 将 plaintexts_SCA.bin, datapoints.bin, SubBytes.bin, HW.bin 放入 data/ python CPA_Attack_Simple.py # 输出:plots/CPA_attack_full_key.png + 恢复的密钥打印到控制台 ``` ## 任务 2 — MATLAB 功耗模型对比 `lab_task2_123.m` 在所有 16 个密钥字节上对比了 **9 种泄漏模型**: | # | 模型 | 描述 | |---|---|---| | 1 | Hamming Weight | 中间值中置位位的总和 | | 2–9 | Bit 0 – Bit 7 | 中间值的单个位(LSB 到 MSB) | 对于每个模型和每个密钥字节,脚本: 1. 对所有 256 个密钥假设计算 `V = SubBytes(D XOR K)`。 2. 根据选定的模型构建假设功耗矩阵 `H`。 3. 计算**全集合**皮尔逊相关性(使用所有 10 000 条轨迹)以确定真实的密钥字节。 4. 从 `[100, 500, 1000, 2000, 5000, 10000]` 中找出**最小轨迹数**,该数量已能恢复相同的密钥字节。 结果保存在 `results` 结构体中,并打印每种模型所需的平均轨迹数。 ### 运行 打开 MATLAB,导航到 `Task2_MATLAB_Code_Files/`,并运行: ``` lab_task2_123 ``` ## Jupyter Notebook (Scared) `Task1_Python_Code_Files/AES_CPA_Scared.ipynb` 使用 **[Scared](https://gitlab.com/eshard/scared)** SCA 框架演示了相同的攻击: | 步骤 | 描述 | |---|---| | 1 | 将明文和轨迹加载到 `TraceHolderSet` (THS) 中 | | 2 | 定义 `FirstSubBytes` 选择函数 | | 3 | 使用 `HammingWeight` 模型和 `maxabs` 判别式实例化 `CPAAttack` | | 4 | 运行 `att.run(container)` | | 5 | 通过 `np.argmax(att.scores, axis=0)` 提取密钥 | | 6 | 可视化每字节的相关性轨迹(正确 vs. 错误假设) | 安装依赖: ``` pip install scared numpy matplotlib ``` ## 结果 | 指标 | 作品集就绪摘要 | |---|---| | 密钥恢复完整性 | **16 / 16 字节已恢复** | | 端到端攻击成功率 | 在收集的数据集上为 **100%** | | 最有效的泄漏模型 | **Hamming Weight (HW)** | | 可靠 HW 恢复所需的轨迹 | **~1,000–2,000 条轨迹** | | 使用的总采集量 | **10,000 条轨迹 × 1,000 个样本** | Hamming Weight 模型持续需要最少的轨迹。单位模型需要更多轨迹,但在数据充足时可以成功,其中高位(接近 MSB)由于泄漏方差较高,通常表现略好。 ## 技术栈 | 层级 | 工具 | |---|---| | **硬件** | STM32 Nucleo, 示波器, 低噪声探头 | | **固件** | C (STM32 HAL/LL), GPIO 触发 | | **Python 分析** | Python 3.10+, NumPy, Matplotlib, Scared | | **MATLAB 分析** | MATLAB R2022b+ | | **Notebook** | Jupyter, ipykernel | ## 设置与使用 ### Python (任务 1 & Notebook) ``` # 创建并激活虚拟环境 python -m venv .venv .venv\Scripts\activate # Windows source .venv/bin/activate # Linux / macOS # 安装依赖 pip install numpy matplotlib scared # 运行任务 1 cd Task1_Python_Code_Files python CPA_Attack_Simple.py # 运行 Notebook cd Task1_Python_Code_Files jupyter notebook AES_CPA_Scared.ipynb ``` ### MATLAB (任务 2) 1. 打开 MATLAB。 2. 切换目录到 `Task2_MATLAB_Code_Files/`。 3. 确保 `attack_data_10k.mat` 和 `constants.mat` 存在。 4. 运行 `lab_task2_123`。 **作者:** Uzair Ashfaq **日期:** 2025年11月
标签:AES-128, ChipWhisperer, CPA攻击, MATLAB, Python, STM32, 云资产清单, 侧信道攻击, 信号处理, 功耗分析, 命令控制, 密码学, 密钥恢复, 嵌入式安全, 手动系统调用, 数据采集, 无后门, 汉明重量, 物理攻击, 相关功耗分析, 硬件安全, 网络安全, 逆向工具, 逆向工程, 隐私保护