FPGA实战(46):基于FPGA的SM3加密算法硬件加速器设计与实现 一、SM3算法概述SM3密码杂凑算法是由国家密码管理局发布的中国商用密码标准算法,2018年正式成为ISO/IEC国际标准(ISO/IEC 10118-3:2018)。该算法采用Merkle-Damgård迭代结构,对输入消息进行填充后,以512比特为单位进行分组处理,最终输出256比特的杂凑值。SM3算法整体流程可分为三个阶段:消息填充、消息扩展和迭代压缩。其中迭代压缩共进行64轮运算,每轮涉及多个32比特字的置换、移位和布尔函数运算。算法的安全性建立在以下核心运算的基础上:P0置换:P0(X) = X ^ (X 9) ^ (X 17)P1置换:P1(X) = X ^ (X 15) ^ (X 23)FFj布尔函数:当0 ≤ j 16时取X ^ Y ^ Z,16 ≤ j 64时取(X Y) | (X Z) | (Y Z)GGj布尔函数:当0 ≤ j 16时取X ^ Y ^ Z,16 ≤ j 64时取(X Y) | (~X Z)SM3算法的64轮迭代中,前16轮与后48轮所使用的布尔函数和常量Tj有所不同,这增强了算法抵抗差分攻击和碰撞攻击的能力。二、整体架构设计本设计采用模块化分层架构,将SM3算法拆分为三个独立的功能模块。顶层模块SM3_Encrypt负责整体调度与流水线控制,Data_Extend模块专职完成消息扩展运算,iterator_module模块实现单轮迭代压缩的核心运算。三个模块之间通过握手信号进行数据传递,形成稳定的流水线结构。顶层模块通过参数PARALLEL_NUM控制迭代压缩阶段的并行度,该参数支持1、2、4、8、16、32、64共七种配置。当并行度为64时,64轮迭代在一个时钟周期内全部展开;当并行度为1时,每时钟周期只完成一轮迭代,需要64个时钟周期完成一次哈希计算。并行度越高,吞吐率越大,但组合逻辑级数也随之增加,对FPGA的时序收敛提出更高要求。模块内部采用了完整的流水线设计,消息扩展、迭代压缩和输出控制三级之间通过寄存器打拍隔离,使得各级可以并行工作。当流水线填满后,系统能够在每个时钟周期输出一个哈希计算结果,达到理论上的最大吞吐率。三、消息扩展模块的实现消息扩展是SM3算法的第一步核心运算,其任务是将512比特的填充消息分组扩展为132个32比特消息字,其中W0至W67用于迭代压缩的Wj输入,W’0至W’63用于W’j输入。标准SM3的消息扩展公式如下:对于16 ≤ j ≤ 67:Wj = P1(Wj-16 ^ Wj-9 ^ (Wj-3 15)) ^ (Wj-13 7) ^ Wj-6对于0 ≤ j ≤ 63:W'j = Wj ^ Wj+4在Data_Extend模块中,前16个消息字W0至W15由填充数据直接转换得到。需要注意的是,SM3采用大端字节序,而Verilog的总线索引默认对应小端序,因此需要通过循环赋值完成字节序转换:assign w_padding_data_f[g_i*32+31 : g_i*32] = ri_padding_data[511 - g_i*32 : 511 - 31 - g_i*32];W16至W67的生成采用组合逻辑实现。P1置换函数通过位拼接操作完成循环左移,避免了使用移位寄存器带来的额外延迟。W’0至W’63则由对应的Wj与Wj+4异或得到。为降低后续迭代压缩模块的访存延迟,本设计将全部132个扩展字一次性计算完毕并存入寄存器阵列,经一拍延迟后输出。iterator_module在每轮迭代中直接从o_extend_data总线中提取所需的Wj和W’j,无需等待扩展模块逐周期计算。四、迭代压缩模块的设计iterator_module模块实现了SM3算法中单轮迭代压缩的全部运算。该模块的输入包括当前轮的8个32比特状态字(A~H)、132个扩展消息字以及当前轮数j,输出为更新后的8个状态字。单轮迭代压缩的运算表达式如下:SS1 = ((A 12) + E + (Tj j)) 7 SS2 = SS1 ^ (A 12) TT1 = FFj(A, B, C, j) + D + SS2 + W'j TT2 = GGj(E, F, G, j) + H + SS1 + Wj D' = C C' = B 9 B' = A A' = TT1 H' = G G' = F 19 F' = E E' = P0(TT2)在硬件实现时,上述表达式中的加法运算全部为32比特模2^32加法,Verilog中直接使用+运算符即可。循环左移通过位拼接操作实现,例如{w_A[19:0], w_A[31:20]}表示将A循环左移12位。在关键路径优化方面,本设计采用了预计算策略。Tj常量的取值仅与轮数j有关,j16时取0x79cc4519,j≥16时取0x7a879d8a。但Tj j需要根据当前轮数进行循环左移,这一操作位于SS1计算的关键路径上。本设计在生成阶段通过genvar循环预先计算出所有64轮的Tj j值并存入w_Tj_y数组,迭代时直接根据i_j索引取出,有效缩短了关键路径长度。FFj和GGj函数使用function实现,综合工具将其映射为纯组合逻辑。前16轮为异或逻辑,后48轮为与或逻辑,综合工具会根据j的取值自动优化为适当的逻辑门级实现。五、并行迭代链的结构顶层模块SM3_Encrypt中最关键的设计在于通过generate语句构造可配置的并行迭代链。PARALLEL_NUM参数决定了每个迭代周期内并行执行的轮数,P_ITERATOR_CYCLE = 64 / PARALLEL_NUM则决定了完成一次完整哈希所需的迭代周期数。当PARALLEL_NUM=4时,每4轮迭代为一个组,组内4个iterator_module通过组合逻辑级联,前一级的输出直接作为后一级的输入。组间则通过寄存器打拍,将上一组的最终状态寄存到下一组的起始寄存器中。r_iterator_V数组用于存储每个迭代周期的初始状态值。r_iterator_V[0]固定为SM3标准规定的初始向量IV:7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e每次迭代完成后,当前组的输出状态被寄存到下一组的输入寄存器中,形成链式传递。当64轮迭代全部完成后,最终状态与初始向量IV异或,得到256比特的杂凑值。这种设计方式将迭代轮数的控制从时序逻辑转移到了组合逻辑中。在FPGA上,组合逻辑的延迟决定了最高工作频率,而并行度越高,组合逻辑级数越多,频率上限越低。因此在实际工程中需要根据目标器件的时序特性选择合适的并行度。六、流水线控制与输出逻辑为了保证数据流的连续性和输出结果的正确性,本设计在多个层面实现了流水线控制。消息有效信号i_Original_Valid在消息扩展阶段被打拍为ri_padding_valid,经过扩展模块的延迟后产生w_extend_valid。该信号随后通过r_cmp_valid移位寄存器链逐级传递,与迭代压缩的进度严格对齐。r_cmp_valid数组的长度为64