密码算法的正确性测试和性能测试
一、总体框架
测试类型总览
| 测试类型 | 方法 | 目的 |
|---|---|---|
| 静态白盒测试 | 对照设计文档检查代码 | 验证实现与算法描述一致 |
| 动态黑盒测试 | 使用标准测试向量 | 验证输入输出正确性 |
| 动态白盒测试 | 检查中间结果和代码覆盖 | 验证内部运算过程正确性 |
| 压力测试 | 随机大量输入 | 检验实现的可靠性和容错能力 |
| 性能测试 | 测量速度和资源占用 | 评估算法实现效率 |
| 其他安全测试 | 侧信道、能量攻击等 | 抵抗物理攻击能力 |
二、静态白盒测试(9.1)
核心思想
测试人员对照算法设计文档,检查代码实现是否正确。
检查内容
- 关键公式是否正确实现
- 程序运行流程是否与算法描述一致
- 程序控制流程
- 输入输出数据
- 程序接口
- 参数类型
三、动态黑盒测试(9.2)
核心原则
测试向量的选取采用等价类划分方法,而非穷举所有可能。
重要:相同的明文、相同的密钥加密后生成相同的密文,不能完全证明算法实现的正确性。还需要动态白盒测试。
3.1 分组密码算法测试向量(以AES为例)
分组长度128bit,密钥长度128bit。划分为8个等价类:
| 等价类编号 | 测试条件 | 设计目的(针对场景) |
|---|---|---|
| 类1 | 明文全为 0,密钥仅 1 个比特位为 1(遍历 128 个位置)。 | 检测算法在极稀疏密钥(只有一个比特活跃)下的非线性扩散能力,验证密钥扩展算法是否会将差异充分扩散。 |
| 类2 | 密钥全为 0,明文仅 1 个比特位为 1(遍历 128 个位置)。 | 检测算法在极稀疏明文下的雪崩效应,验证明文的单比特变化是否引起密文的广泛变化。 |
| 类3 | 密钥与明文取值相同,且每个字节均相同(从 0x00 到 0xFF,共 256 个用例)。 | 检测在明文与密钥高度结构化/相等时的算法输出随机性,避免特定对称关系导致弱密钥或碰撞。 |
| 类4 | 随机生成多组(如 2 组)明文和密钥。 | 常规功能验证,模拟正常使用场景下的加解密正确性。 |
| 类5(反向) | 密文全为 0,密钥仅 1 个比特位为 1(先解密得到明文,再加密比对)。 | 验证解密函数的正确性,确保在极端密文输入下解密模块能正确恢复明文,且加解密函数互逆。 |
| 类6(反向) | 密钥全为 0,密文仅 1 个比特位为 1(先解密再加密)。 | 验证解密函数对稀疏密文的处理能力,确保逆运算的扩散性。 |
| 类7(反向) | 密钥与密文相同,每个字节均相同(0x00~0xFF,先解密再加密)。 | 验证极端关联数据下的解密稳定性,防止解密函数存在数值溢出或除零等隐性缺陷。 |
| 类8(性能辅助) | 选取典型用例,连续执行加密 100 次和 1000 次并校验结果。 | 验证算法实现的幂等性和状态复位机制,确保多次调用无累积状态污染。 |
每组测试向量还给出加密100次和1000次的结果。
DES测试向量
- 分组长度和密钥长度均为64bit
- 划分方法同AES,8个等价类
3.2 序列密码算法测试向量(以Rabbit为例)
种子密钥128bit,初始向量64bit。划分为6个等价类:
| 编号 | 条件 | 说明 |
|---|---|---|
| 1 | IV全0,密钥有1位为1 | 测试密钥单比特变化 |
| 2 | IV全0,密钥每个字节相同 | 256个用例(字节00~FF) |
| 3 | IV全0,密钥第1字节00~FF,后续字节逐字节+1(模256) | 测试密钥连续性变化 |
| 4 | IV全0,密钥随机生成 | 给出前131072字节密钥流中的部分 |
| 5 | 密钥全0,IV有1位为1 | 64个用例,给出前512字节密钥流 |
| 6 | IV和密钥随机生成 | 给出前131072字节密钥流中的部分 |
Mickey算法测试向量选取方法同Rabbit,6个等价类。
序列密码测试要点
- 不仅要给出前面产生的密钥流,还要给出运行若干拍后产生的密钥流。
- 原因:序列密码可能存在初始化阶段的不稳定性,早期密钥流和稳定后的密钥流特性可能不同;部分序列密码需要"预热"若干拍后才能达到良好的随机性。
3.3 正确测试向量来源
- 算法征集过程中,征集方要求设计者提供正确测试向量
- 摘要算法、加密认证算法、公钥算法同理
- 设计者在提交时需提供足够多的测试向量
四、动态白盒测试(9.3)
4.1 算法运算中间结果
密码算法设计者除提供输入输出外,还需提供加密过程中的中间结果。
分组密码示例(ARIA算法)
| 测试用例 | 内容 |
|---|---|
| 1 | 密钥扩展后各轮子密钥计算结果 |
| 2 | 每组明文和密钥每一轮加解密后的计算结果 |
| 3 | 一组密钥+IV,10组明文,不同工作模式下加密结果 |
序列密码
- 提供密钥流生成过程的状态变量
- 种子密钥扩展后各个状态
- 不同时刻的线性反馈移位寄存器(LFSR)状态
- 记忆状态
- 重点关注时序问题
4.2 算法实现代码测试
1)数据流覆盖
| 测试类型 | 内容 |
|---|---|
| 边界测试 | 寻找特殊测试向量(如全0) |
| 次边界测试 | 循环边界、逻辑判断边界 |
| 空值和无效数据 | 密钥/明文为空或长度不够时的处理(反映可靠性和容错能力) |
2)代码覆盖
- 程序语句和代码行覆盖
- 分支覆盖
- 条件覆盖
五、压力测试(9.4)
核心思想
随机生成各种输入值,与参考实现程序的运算结果对比。
目的
检查算法实现的正确性和可靠性。
关键问题
参考程序从哪来?
- 设计者提供的参考实现
- 标准中的参考代码
六、性能测试(9.5)
6.1 算法运行速度
单位
- 一般以 MB/s 或 Mb/s 为单位
- 必须说明运行平台环境(离开环境,速度无意义)
分组密码
- 给出加密速度和解密速度
- 分别给出长字节和短字节数据加解密速度
- 分析:长字节/短字节哪个更快?
序列密码
- 给出生成密钥流的速度
- 分别给出长密钥流和短密钥流的生成速度
平台无关度量:cycle/B
\[\text{cycle/B} = \text{处理一个字节数据需要的机器周期数}
\]
优点:与运行平台无关。需要将代码转为汇编语言,统计所有代码的机器周期。
6.2 代码空间和数据空间
| 空间类型 | 含义 |
|---|---|
| 程序空间 | 编译后生成的可执行二进制码文件大小 |
| 数据空间(静态) | 大的算法参数等占用的空间 |
| 数据空间(运行时) | 运行时占用的内存空间大小 |
- 静态空间估算:主要考虑大的算法参数等
- 也可用压力测试测试对外部资源的依赖程度
七、其他安全测试
常见攻击方式
- 侧信道攻击(Side-Channel Attack)
- 能量攻击(Power Analysis)
- 渗透攻击
防护与测评
- 实际系统中采用各种方法进行保护
- 制定相应标准提出安全要求和测评要求
- 测试人员结合具体标准和设计的安全需求进行测试
八、测试方法对比总结
| 静态白盒 | 动态黑盒 | 动态白盒 | 压力测试 | 性能测试 | |
|---|---|---|---|---|---|
| 是否运行代码 | 否(代码审查) | 是 | 是 | 是 | 是 |
| 是否需要设计文档 | 是 | 否(需测试向量) | 是 | 否 | 否 |
| 主要检查内容 | 流程/接口/公式 | 输入输出正确性 | 中间状态/代码覆盖 | 异常输入处理 | 速度/空间 |
| 测试向量 | 不需要 | 等价类划分 | 设计者提供中间值 | 随机生成 | 标准测试数据 |
- cycle/B的优点:cycle/B指处理一个字节数据需要的机器周期数。将代码转为汇编语言统计周期,去除了不同CPU主频、内存速度等硬件差异,使得算法性能对比具有客观性和平台无关性。
- 注明环境的原因:算法运行速度(MB/s)受编译优化等级、操作系统调度、处理器微架构等影响极大。脱离了运行平台环境(如CPU型号、主频、编译器版本),速度数据不具备横向可比性,也无实际参考价值。

浙公网安备 33010602011771号