阶段四侧信道防护 — 随机化调度通过打乱操作顺序、插入随机延迟和伪操作,使功耗轨迹对齐变得困难,从而削弱 DPA 攻击。
DPA 的核心步骤是将功耗轨迹对齐——确保相同操作在不同轨迹中出现在相同时间点。随机化调度破坏这个前提。
在关键操作前后插入随机数量的空操作(NOP),使操作时间点随机偏移:
// random_delay.v - 随机延迟模块
module random_delay #(
parameter MAX_DELAY = 15, // 最大延迟周期数
parameter DELAY_BITS = 4 // 延迟位数
)(
input wire clk,
input wire rst_n,
input wire trigger, // 触发延迟
input wire [DELAY_BITS-1:0] random_val,// 随机延迟值
output reg delay_done // 延迟完成
);
reg [DELAY_BITS-1:0] counter;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
counter <= 0;
delay_done <= 1;
end else if (trigger) begin
counter <= random_val[DELAY_BITS-1:0];
delay_done <= 0;
end else if (counter > 0) begin
counter <= counter - 1;
delay_done <= 0;
end else begin
delay_done <= 1;
end
end
endmodule
AES 的 16 个 S-Box 操作是独立的,可以随机排列执行顺序:
// random_scheduler.v - 随机操作调度器
module random_scheduler #(
parameter NUM_OPS = 16, // 操作数量
parameter OP_BITS = 4 // 操作索引位数
)(
input wire clk,
input wire rst_n,
input wire start,
input wire [NUM_OPS*4-1:0] perm_seed, // 随机排列种子
output reg [OP_BITS-1:0] op_index, // 当前操作索引
output reg op_valid, // 操作有效
output reg all_done // 所有操作完成
);
// Fisher-Yates 洗牌算法的硬件实现
reg [OP_BITS-1:0] schedule [0:NUM_OPS-1];
reg [OP_BITS-1:0] current_idx;
reg running;
integer i;
initial begin
for (i = 0; i < NUM_OPS; i = i + 1)
schedule[i] = i[OP_BITS-1:0];
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
op_index <= 0; op_valid <= 0;
all_done <= 0; running <= 0;
current_idx <= 0;
end else if (start && !running) begin
// 使用种子生成随机排列
// 简化实现:使用种子作为初始偏移
for (i = 0; i < NUM_OPS; i = i + 1)
schedule[i] <= (i[OP_BITS-1:0] + perm_seed[i*4+:4]) % NUM_OPS;
current_idx <= 0;
running <= 1;
all_done <= 0;
end else if (running) begin
if (current_idx < NUM_OPS) begin
op_index <= schedule[current_idx];
op_valid <= 1;
current_idx <= current_idx + 1;
end else begin
op_valid <= 0;
all_done <= 1;
running <= 0;
end
end
end
endmodule
在真实操作之间插入随机数量的假操作(使用随机数据),增加功耗噪声:
// dummy_ops.v - 伪操作注入模块
module dummy_ops #(
parameter WIDTH = 128,
parameter MAX_DUMMY = 3
)(
input wire clk,
input wire rst_n,
input wire real_op_start, // 真实操作开始
input wire [7:0] random_ctrl, // 随机控制
input wire [WIDTH-1:0] real_data, // 真实数据
output reg executing, // 正在执行
output reg is_real, // 当前是真实操作
output reg [WIDTH-1:0] active_data // 当前活跃数据
);
reg [1:0] dummy_count;
reg [1:0] dummy_target;
reg in_dummy;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
executing <= 0; is_real <= 0;
active_data <= 0; dummy_count <= 0;
in_dummy <= 0; dummy_target <= 0;
end else if (real_op_start) begin
// 决定插入多少伪操作
dummy_target <= random_ctrl[7:6]; // 0-3 个
dummy_count <= 0;
if (random_ctrl[7:6] > 0) begin
in_dummy <= 1;
is_real <= 0;
active_data <= {random_ctrl, {WIDTH-8{1'b0}}}; // 伪数据
executing <= 1;
end else begin
in_dummy <= 0;
is_real <= 1;
active_data <= real_data;
executing <= 1;
end
end else if (executing) begin
if (in_dummy) begin
dummy_count <= dummy_count + 1;
if (dummy_count >= dummy_target - 1) begin
in_dummy <= 0;
is_real <= 1;
active_data <= real_data;
end else begin
active_data <= active_data ^ {random_ctrl, {WIDTH-8{1'b0}}};
end
end else begin
executing <= 0;
end
end
end
endmodule
随机化调度的效果取决于随机化程度和攻击者的对齐能力:
例如,如果 AES 的 16 个 S-Box 操作随机排列,DPA 攻击需要约 16² = 256 倍的轨迹数量才能达到相同效果。
1. 实现随机延迟 AES:在每轮 SubBytes 前插入随机延迟,测量 DPA 攻击的轨迹数量需求变化。
2. 设计一个随机化的 AES 轮函数:16 个 S-Box 以随机顺序执行,每个 S-Box 前后随机延迟。
3. 分析:随机化调度能否单独提供足够的安全保护?还是需要与掩码结合?
4. 实现动态频率调整:在关键操作时随机切换时钟频率。
你已掌握随机化调度的三大技术:随机延迟、随机操作顺序和伪操作注入,以及它们对 DPA 攻击的削弱效果。
获得徽章:🌪️ CHAOS_MASTER
推荐使用以下工具链进行课程实践:
# 安装 Verilator
sudo apt install verilator
# 安装 Icarus Verilog(可选)
sudo apt install iverilog
# 安装 GTKWave(波形查看器)
sudo apt install gtkwave
# 验证安装
verilator --lint-only --version
iverilog -V
密码学硬件实现的关键性能指标:
这些指标之间通常存在 trade-off,设计时需根据应用场景权衡。
本课涉及的核心概念和技术关系:
Verilog 仿真调试的常用方法:
// 调试示例
initial begin
$dumpfile("sim.vcd");
$dumpvars(0, uut);
end
// 断言验证
assert property (@(posedge clk) valid |-> data !== 'x)
else $error("Invalid data when valid!");
# 1. 语法检查
verilator --lint-only module.v
# 2. 创建 C++ 测试主函数
cat > sim_main.cpp << 'EOF'
#include "Vmodule.h"
#include "verilated.h"
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
Vmodule* top = new Vmodule;
top->clk = 0; top->rst_n = 0;
top->eval();
top->rst_n = 1;
for (int i = 0; i < 100; i++) {
top->clk = !top->clk;
top->eval();
}
delete top;
return 0;
}
EOF
# 3. 编译
verilator -cc module.v --exe sim_main.cpp
make -C obj_dir -f Vmodule.mk
# 4. 运行
./obj_dir/Vmodule
密码硬件的性能评估维度:
| 指标 | 单位 | 说明 |
|---|---|---|
| 面积 | GE / LUT | 等效门数或查找表数量 |
| 频率 | MHz | 最大时钟频率 |
| 吞吐量 | Gbps | 每秒处理的数据量 |
| 延迟 | 周期数 | 从输入到输出的周期 |
| 能效 | pJ/bit | 每比特能耗 |
| 面积效率 | Gbps/GE | 单位面积吞吐量 |
不同应用场景对指标优先级不同:IoT 偏重面积和能效,服务器偏重吞吐量。
本课涉及的核心概念和技术关系:
Verilog 仿真调试的常用方法:
// 调试示例
initial begin
$dumpfile("sim.vcd");
$dumpvars(0, uut);
end
// 断言验证
assert property (@(posedge clk) valid |-> data !== 'x)
else $error("Invalid data when valid!");
# 1. 语法检查
verilator --lint-only module.v
# 2. 创建 C++ 测试主函数
cat > sim_main.cpp << 'EOF'
#include "Vmodule.h"
#include "verilated.h"
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
Vmodule* top = new Vmodule;
top->clk = 0; top->rst_n = 0;
top->eval();
top->rst_n = 1;
for (int i = 0; i < 100; i++) {
top->clk = !top->clk;
top->eval();
}
delete top;
return 0;
}
EOF
# 3. 编译
verilator -cc module.v --exe sim_main.cpp
make -C obj_dir -f Vmodule.mk
# 4. 运行
./obj_dir/Vmodule
密码硬件的性能评估维度:
| 指标 | 单位 | 说明 |
|---|---|---|
| 面积 | GE / LUT | 等效门数或查找表数量 |
| 频率 | MHz | 最大时钟频率 |
| 吞吐量 | Gbps | 每秒处理的数据量 |
| 延迟 | 周期数 | 从输入到输出的周期 |
| 能效 | pJ/bit | 每比特能耗 |
| 面积效率 | Gbps/GE | 单位面积吞吐量 |
不同应用场景对指标优先级不同:IoT 偏重面积和能效,服务器偏重吞吐量。