SM3:密码学杂凑函数

国家标准全文公开系统:http://openstd.samr.gov.cn/

本文参考:http://c.gb688.cn/bzgk/gb/showGb?type=online&hcno=45B1A67F20F3BF339211C391E9278F5E

常数与函数

  • 初值 I V = 7380166 F , 4914 B 2 B 9 , 172442 D 7 , D A 8 A 0600 , A 96 F 30 B C , 163138 A A , E 38 D E E 4 D , B 0 F B 0 E 4 E IV = 7380166F,4914B2B9,172442D7,DA8A0600,A96F30BC,163138AA,E38DEE4D,B0FB0E4E IV=7380166F,4914B2B9,172442D7,DA8A0600,A96F30BC,163138AA,E38DEE4D,B0FB0E4E

  • 常量 T 0 = 79 C C 4519 ,   T 1 = 7 A 879 D 8 A T_0 = 79CC4519,\,T_1 = 7A879D8A T0=79CC4519,T1=7A879D8A

  • 布尔函数
    F F 0 ( X , Y , Z ) = X ⊕ Y ⊕ Z 模 2 加 法 F F 1 ( X , Y , Z ) = ( X ∧ Y ) ∨ ( X ∧ Z ) ∨ ( Y ∧ Z ) 少 数 服 从 多 数 G G 0 ( X , Y , Z ) = X ⊕ Y ⊕ Z 模 2 加 法 G G 1 ( X , Y , Z ) = ( X ∧ Y ) ∨ ( ¬ X ∧ Z ) 用 X 选 择 Y 或 Z \begin{aligned} FF_0(X,Y,Z) =& X \oplus Y \oplus Z & 模2加法\\ FF_1(X,Y,Z) =& (X \wedge Y) \vee (X \wedge Z) \vee (Y \wedge Z) & 少数服从多数\\ GG_0(X,Y,Z) =& X \oplus Y \oplus Z & 模2加法\\ GG_1(X,Y,Z) =& (X \wedge Y) \vee (\neg X \wedge Z) & 用X选择Y或Z\\ \end{aligned} FF0(X,Y,Z)=FF1(X,Y,Z)=GG0(X,Y,Z)=GG1(X,Y,Z)=XYZ(XY)(XZ)(YZ)XYZ(XY)(¬XZ)22XYZ

  • 置换函数
    P 0 ( X ) = X ⊕ ( X ≪ 9 ) ⊕ ( X ≪ 17 ) P 1 ( X ) = X ⊕ ( X ≪ 15 ) ⊕ ( X ≪ 23 ) \begin{aligned} P_0(X) =& X \oplus (X \ll 9) \oplus (X \ll 17) \\ P_1(X) =& X \oplus (X \ll 15) \oplus (X \ll 23) \\ \end{aligned} P0(X)=P1(X)=X(X9)(X17)X(X15)(X23)

  • 其中 X , Y , Z X,Y,Z X,Y,Z都是,运算符 ≪ \ll 是字的循环左移

  • S M 3 SM3 SM3处理的单位是字 (1 Word = 32 bits),按大端存储 (左边是高有效位)

消息扩展

  • 512 512 512比特的消息分组 (含 16 16 16个字 W 0 , W 1 , ⋯   , W 15 W_0,W_1,\cdots,W_{15} W0,W1,,W15),扩展成 132 132 132个字 W 0 , W 1 , ⋯   , W 67 , W 0 ′ , W 1 ′ , ⋯   , W 63 ′ W_0,W_1,\cdots,W_{67},W_0',W_1',\cdots,W_{63}' W0,W1,,W67,W0,W1,,W63

  • 对于 i = 16 , 17 , ⋯   , 67 i=16,17,\cdots,67 i=16,17,,67,计算 W i = P 1 ( W i − 16 ⊕ W i − 9 ⊕ ( W i − 3 ≪ 15 ) ) ⊕ ( W i − 13 ≪ 7 ) ⊕ W i − 6 W_i = P_1(W_{i-16} \oplus W_{i-9} \oplus (W_{i-3} \ll 15)) \oplus (W_{i-13} \ll 7) \oplus W_{i-6} Wi=P1(Wi16Wi9(Wi315))(Wi137)Wi6

  • 对于 j = 0 , 1 , ⋯   , 63 j = 0,1,\cdots,63 j=0,1,,63,计算 W j ′ = W j ⊕ W j + 4 W_j' = W_j \oplus W_{j+4} Wj=WjWj+4

压缩函数

  • 这是固定输入长度 512 512 512比特的压缩函数,输出为 256 256 256比特的杂凑值。

  • 记为 V ′ = C F ( V , B ) V' = CF(V,B) V=CF(V,B),其中 V , V ′ V,V' V,V中间变量 B B B 512 512 512比特的输入。

  • A B C D E F G H ← V ABCDEFGH \leftarrow V ABCDEFGHV,其中 A , B , ⋯ A,B,\cdots A,B, 32 32 32比特的字。

  • 一共要执行 64 64 64轮迭代,然后 V ′ ← A B C D E F G H ⊕ V V' \leftarrow ABCDEFGH \oplus V VABCDEFGHV

  • 对于 0 ≤ j ≤ 15 0 \le j \le 15 0j15的迭代,使用 T 0 , F F 0 , G G 0 T_0,FF_0,GG_0 T0,FF0,GG0 P 0 P_0 P0

  • 对于 16 ≤ j ≤ 63 16 \le j \le 63 16j63的迭代,使用 T 1 , F F 1 , G G 1 T_1,FF_1,GG_1 T1,FF1,GG1 P 0 P_0 P0

for (j = 0; j < 16; j++)
{
    SS1 = ROTL((ROTL(A, 12) + E + ROTL(T0, j)), 7);
    SS2 = SS1 ^ ROTL(A, 12);
    TT1 = FF0(A, B, C) + D + SS2 + W1[j];
    TT2 = GG0(E, F, G) + H + SS1 + W[j];
    D = C;
    C = ROTL(B, 9);
    B = A;
    A = TT1;
    H = G;
    G = ROTL(F, 19);
    F = E;
    E = P0(TT2);
}

for (j = 16; j < 64; j++)
{
    SS1 = ROTL((ROTL(A, 12) + E + ROTL(T1, j)), 7);
    SS2 = SS1 ^ ROTL(A, 12);
    TT1 = FF1(A, B, C) + D + SS2 + W1[j];
    TT2 = GG1(E, F, G) + H + SS1 + W[j];
    D = C;
    C = ROTL(B, 9);
    B = A;
    A = TT1;
    H = G;
    G = ROTL(F, 19);
    F = E;
    E = P0(TT2);
}

填充

  • 对于 l < 2 64 l < 2^{64} l<264比特长度的消息 m m m,计算 k = min ⁡ { k ≥ 0 ∣ l + 1 + k ≡ 448 m o d    512 } k = \min\{k \ge 0 \mid l+1+k \equiv 448 \mod 512\} k=min{k0l+1+k448mod512}
  • 做填充: m ′ = m ∥ 1 ∥ 0 ⋯ 0 ⏟ k ∥ l m' = m \| 1 \| \underbrace{0 \cdots 0}_{k} \| l m=m1k 00l,其中 l l l 64 64 64比特的无符号整数。
  • 填充后的消息 m ′ m' m长度为 512 512 512的倍数 l ′ l' l,它的最后 64 64 64比特是消息长度,然后继续向前找到第一个遇到的 1 1 1作为标记,继续往前就是消息 m m m

迭代压缩

  • 使用 M e r k l e − D a m g a r d      T r a n s f o r m Merkle-Damgard\,\,\,\,Transform MerkleDamgardTransform,将固定输入长度的压缩函数,扩展到任意输入长度的压缩函数。
  • 假设填充后的 m ′ m' m长度为 l ′ = 512 n l' = 512n l=512n,那么可以分成 n n n 512 512 512比特的消息分组 B ( i ) ,   i = 0 , 1 , ⋯   , n − 1 B^{(i)},\, i=0,1,\cdots,n-1 B(i),i=0,1,,n1
  • 初始化 V ( 0 ) = I V V^{(0)} = IV V(0)=IV
  • 迭代 V ( i + 1 ) = C F ( V ( i ) , B ( i ) ) V^{(i+1)} = CF(V^{(i)},B^{(i)}) V(i+1)=CF(V(i),B(i)),最后输出 V ( n ) V^{(n)} V(n)

在线计算

  • 有时候,我们并不知道要压缩的消息 m m m到底有多长。比如:网络通信中,数据包分批到达。
  • 可以记录当前已到达的数据长度,对已到达的数据分组并迭代计算中间变量 V ( j ) V^{(j)} V(j),并存储达不到 512 512 512比特的数据尾部。
  • 填充步骤放在最后执行。当所有数据都到达之后,对数据尾部做填充,并迭代计算出 V ( n ) V^{(n)} V(n)

实现

  • 不同计算机的大小端不一致。

  • 小端机器上, u i n t 32    n = 0 x 01020304 uint32\,\,n = 0x01020304 uint32n=0x01020304,对应 ( u i n t 8 ∗ )    & n = [ 04 , 03 , 02 , 01 ] (uint8*)\,\,\&n = [04,03,02,01] (uint8)&n=[04,03,02,01]

  • 本人的笔记本为小端机器,执行 C F CF CF时注意数据的大小端转换。

  • C F CF CF中, A → B A \rightarrow B AB C → D C \rightarrow D CD E → F E \rightarrow F EF G → H G \rightarrow H GH这些赋值不是必要的,可以跨越两轮。赋值运算比位运算要慢得多。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值