smcrypto/
sm3.rs

1use std::vec;
2
3fn sm3_ff_j(x: u32, y: u32, z: u32, j: u32) -> u32 {
4    let mut ret = 0;
5    if j < 16 {
6        ret = x ^ y ^ z;
7    } else if 16 <= j && j < 64 {
8        ret = (x & y) | (x & z) | (y & z);
9    }
10    ret
11}
12
13fn sm3_gg_j(x: u32, y: u32, z: u32, j: u32) -> u32 {
14    let mut ret = 0;
15    if j < 16 {
16        ret = x ^ y ^ z;
17    } else if 16 <= j && j < 64 {
18        ret = (x & y) | (!x & z)
19    }
20    ret
21}
22
23fn sm3_p_0(x: u32) -> u32 {
24    x ^ x.rotate_left(9) ^ x.rotate_left(17)
25}
26
27fn sm3_p_1(x: u32) -> u32 {
28    x ^ x.rotate_left(15) ^ x.rotate_left(23)
29}
30
31fn sm3_cf(v_i: &Vec<u32>, b_i: &Vec<u32>) -> Vec<u32> {
32    let t_j: Vec<u32> = vec![
33    2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169,
34    2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169,
35    2043430169, 2043430169, 2043430169, 2043430169, 2055708042, 2055708042,
36    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
37    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
38    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
39    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
40    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
41    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
42    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
43    2055708042, 2055708042, 2055708042, 2055708042
44    ];
45    let mut w: Vec<u32> = Vec::with_capacity(68);
46    for i in 0..16 {
47        let mut weight = 0x1000000;
48        let mut data: u32 = 0;
49        for k in (i * 4)..((i + 1) * 4) {
50            data = data.wrapping_add(b_i[k] * weight);
51            weight /= 0x100;
52        }
53        w.push(data);
54    }
55    for j in 16..68 {
56        w.push(sm3_p_1(w[j - 16] ^ w[j - 9] ^ w[j - 3].rotate_left(15)) ^ w[j - 13].rotate_left(7) ^ w[j - 6]);
57    }
58    let mut w_1: Vec<u32> = Vec::with_capacity(64);
59    for j in 0..64 {
60        w_1.push( w[j] ^ w[j + 4]);
61    }
62    let mut a = v_i[0];
63    let mut b = v_i[1];
64    let mut c = v_i[2];
65    let mut d = v_i[3];
66    let mut e = v_i[4];
67    let mut f = v_i[5];
68    let mut g = v_i[6];
69    let mut h = v_i[7];
70    for j in 0..64 {
71        let ss_1 = ((a.rotate_left(12).wrapping_add(e).wrapping_add(t_j[j].rotate_left(j as u32))) & 0xffffffff).rotate_left(7);
72        let ss_2 = ss_1 ^ a.rotate_left(12);
73        let tt_1 = (sm3_ff_j(a, b, c, j as u32).wrapping_add(d).wrapping_add(ss_2).wrapping_add(w_1[j])) & 0xffffffff;
74        let tt_2 = (sm3_gg_j(e, f, g, j as u32).wrapping_add(h).wrapping_add(ss_1).wrapping_add(w[j])) & 0xffffffff;
75        d = c;
76        c = b.rotate_left(9);
77        b = a;
78        a = tt_1;
79        h = g;
80        g = f.rotate_left(19);
81        f = e;
82        e = sm3_p_0(tt_2);
83        a = a & 0xFFFFFFFF;
84        b = b & 0xFFFFFFFF;
85        c = c & 0xFFFFFFFF;
86        d = d & 0xFFFFFFFF;
87        e = e & 0xFFFFFFFF;
88        f = f & 0xFFFFFFFF;
89        g = g & 0xFFFFFFFF;
90        h = h & 0xFFFFFFFF;
91    }
92    let mut cf: Vec<u32> = Vec::with_capacity(8);
93    let v_j: Vec<u32> = vec![a, b, c, d, e, f, g, h];
94    for i in 0..8 {
95        cf.push(v_j[i] ^ v_i[i]);
96    }
97    cf
98}
99
100pub fn sm3_hash_raw(msg: &[u8]) -> Vec<u8> {
101    let iv: Vec<u32> = vec![
102    1937774191, 1226093241, 388252375, 3666478592,
103    2842636476, 372324522, 3817729613, 2969243214,
104    ];
105    let len = msg.len();
106    let reserve = len % 64 + 1;
107    let len_pad = match reserve > 56 {
108        true => len + 130 - reserve,
109        false => len + 66 - reserve
110    };
111    let range_end = match reserve > 56 {
112        true => 120,
113        false => 56
114    };
115    let mut msg_pad: Vec<u8> = Vec::with_capacity(len_pad);
116    msg_pad.extend_from_slice(msg);
117    msg_pad.push(0x80);
118    for _ in reserve..range_end {
119        msg_pad.push(0x00);
120    }
121    let mut bit_length: usize = len * 8;
122    let mut bit_length_str: Vec<usize> = Vec::with_capacity(8);
123    bit_length_str.push(bit_length % 0x100);
124    for _ in 0..7 {
125        bit_length /= 0x100;
126        bit_length_str.push(bit_length % 0x100);
127    }
128    for i in 0..8 {
129        msg_pad.push(bit_length_str[7 - i] as u8);
130    }
131    let group_count: usize = len_pad / 64;
132    let mut b: Vec<Vec<u32>> = Vec::with_capacity(group_count);
133    for _ in 0..group_count {
134        b.push(Vec::with_capacity(64));
135    }
136    for i in 0..group_count {
137        b[i] = msg_pad[(i * 64)..((i + 1) * 64)].iter().map(|x| x.to_be() as u32).collect();
138    }
139    let mut v: Vec<Vec<u32>> = Vec::with_capacity(group_count + 1);
140    for _ in 0..(group_count + 1) {
141        v.push(Vec::with_capacity(8));
142    }
143    v[0] = iv;
144    for i in 0..group_count {
145        v[i + 1] = sm3_cf(&v[i], &b[i]);
146    }
147    let y = &v[group_count];
148    y.into_iter().flat_map(|x| x.to_be_bytes()).collect()
149}
150
151pub fn sm3_hash(msg: &[u8]) -> String {
152    let hash = sm3_hash_raw(msg);
153    hash.iter().map(|x| format!("{:02x}", x)).collect()
154}
155
156pub fn sm3_hash_file(input_file: &str) -> String {
157    let input_file = std::path::Path::new(input_file);
158    let input_data = std::fs::read(input_file).unwrap();
159    sm3_hash(&input_data)
160}
161
162pub fn sm3_hash_string(msg_str: &str) -> String {
163    let msg = msg_str.as_bytes();
164    sm3_hash(msg)
165}