1
15
16 package sm3
17
18 import (
19 "encoding/binary"
20 "hash"
21 )
22
23 type SM3 struct {
24 digest [8]uint32
25 length uint64
26 unhandleMsg []byte
27 }
28
29 func (sm3 *SM3) ff0(x, y, z uint32) uint32 { return x ^ y ^ z }
30
31 func (sm3 *SM3) ff1(x, y, z uint32) uint32 { return (x & y) | (x & z) | (y & z) }
32
33 func (sm3 *SM3) gg0(x, y, z uint32) uint32 { return x ^ y ^ z }
34
35 func (sm3 *SM3) gg1(x, y, z uint32) uint32 { return (x & y) | (^x & z) }
36
37 func (sm3 *SM3) p0(x uint32) uint32 { return x ^ sm3.leftRotate(x, 9) ^ sm3.leftRotate(x, 17) }
38
39 func (sm3 *SM3) p1(x uint32) uint32 { return x ^ sm3.leftRotate(x, 15) ^ sm3.leftRotate(x, 23) }
40
41 func (sm3 *SM3) leftRotate(x uint32, i uint32) uint32 { return x<<(i%32) | x>>(32-i%32) }
42
43 func (sm3 *SM3) pad() []byte {
44 msg := sm3.unhandleMsg
45 msg = append(msg, 0x80)
46 blockSize := 64
47 for len(msg)%blockSize != 56 {
48 msg = append(msg, 0x00)
49 }
50
51 msg = append(msg, uint8(sm3.length>>56&0xff))
52 msg = append(msg, uint8(sm3.length>>48&0xff))
53 msg = append(msg, uint8(sm3.length>>40&0xff))
54 msg = append(msg, uint8(sm3.length>>32&0xff))
55 msg = append(msg, uint8(sm3.length>>24&0xff))
56 msg = append(msg, uint8(sm3.length>>16&0xff))
57 msg = append(msg, uint8(sm3.length>>8&0xff))
58 msg = append(msg, uint8(sm3.length>>0&0xff))
59
60 if len(msg)%64 != 0 {
61 panic("------SM3 Pad: error msgLen =")
62 }
63 return msg
64 }
65
66 func (sm3 *SM3) update(msg []byte) {
67 var w [68]uint32
68 var w1 [64]uint32
69
70 a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
71 for len(msg) >= 64 {
72 for i := 0; i < 16; i++ {
73 w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
74 }
75 for i := 16; i < 68; i++ {
76 w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
77 }
78 for i := 0; i < 64; i++ {
79 w1[i] = w[i] ^ w[i+4]
80 }
81 A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
82 for i := 0; i < 16; i++ {
83 SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
84 SS2 := SS1 ^ sm3.leftRotate(A, 12)
85 TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
86 TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
87 D = C
88 C = sm3.leftRotate(B, 9)
89 B = A
90 A = TT1
91 H = G
92 G = sm3.leftRotate(F, 19)
93 F = E
94 E = sm3.p0(TT2)
95 }
96 for i := 16; i < 64; i++ {
97 SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
98 SS2 := SS1 ^ sm3.leftRotate(A, 12)
99 TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
100 TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
101 D = C
102 C = sm3.leftRotate(B, 9)
103 B = A
104 A = TT1
105 H = G
106 G = sm3.leftRotate(F, 19)
107 F = E
108 E = sm3.p0(TT2)
109 }
110 a ^= A
111 b ^= B
112 c ^= C
113 d ^= D
114 e ^= E
115 f ^= F
116 g ^= G
117 h ^= H
118 msg = msg[64:]
119 }
120 sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7] = a, b, c, d, e, f, g, h
121 }
122 func (sm3 *SM3) update2(msg []byte,) [8]uint32 {
123 var w [68]uint32
124 var w1 [64]uint32
125
126 a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
127 for len(msg) >= 64 {
128 for i := 0; i < 16; i++ {
129 w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
130 }
131 for i := 16; i < 68; i++ {
132 w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
133 }
134 for i := 0; i < 64; i++ {
135 w1[i] = w[i] ^ w[i+4]
136 }
137 A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
138 for i := 0; i < 16; i++ {
139 SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
140 SS2 := SS1 ^ sm3.leftRotate(A, 12)
141 TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
142 TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
143 D = C
144 C = sm3.leftRotate(B, 9)
145 B = A
146 A = TT1
147 H = G
148 G = sm3.leftRotate(F, 19)
149 F = E
150 E = sm3.p0(TT2)
151 }
152 for i := 16; i < 64; i++ {
153 SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
154 SS2 := SS1 ^ sm3.leftRotate(A, 12)
155 TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
156 TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
157 D = C
158 C = sm3.leftRotate(B, 9)
159 B = A
160 A = TT1
161 H = G
162 G = sm3.leftRotate(F, 19)
163 F = E
164 E = sm3.p0(TT2)
165 }
166 a ^= A
167 b ^= B
168 c ^= C
169 d ^= D
170 e ^= E
171 f ^= F
172 g ^= G
173 h ^= H
174 msg = msg[64:]
175 }
176 var digest [8]uint32
177 digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7] = a, b, c, d, e, f, g, h
178 return digest
179 }
180
181
182 func New() hash.Hash {
183 var sm3 SM3
184
185 sm3.Reset()
186 return &sm3
187 }
188
189
190
191
192
193 func (sm3 *SM3) BlockSize() int { return 64 }
194
195
196 func (sm3 *SM3) Size() int { return 32 }
197
198
199
200 func (sm3 *SM3) Reset() {
201
202 sm3.digest[0] = 0x7380166f
203 sm3.digest[1] = 0x4914b2b9
204 sm3.digest[2] = 0x172442d7
205 sm3.digest[3] = 0xda8a0600
206 sm3.digest[4] = 0xa96f30bc
207 sm3.digest[5] = 0x163138aa
208 sm3.digest[6] = 0xe38dee4d
209 sm3.digest[7] = 0xb0fb0e4e
210
211 sm3.length = 0
212 sm3.unhandleMsg = []byte{}
213 }
214
215
216
217 func (sm3 *SM3) Write(p []byte) (int, error) {
218 toWrite := len(p)
219 sm3.length += uint64(len(p) * 8)
220 msg := append(sm3.unhandleMsg, p...)
221 nblocks := len(msg) / sm3.BlockSize()
222 sm3.update(msg)
223
224 sm3.unhandleMsg = msg[nblocks*sm3.BlockSize():]
225
226 return toWrite, nil
227 }
228
229
230
231
232 func (sm3 *SM3) Sum(in []byte) []byte {
233 _, _ = sm3.Write(in)
234 msg := sm3.pad()
235
236 digest := sm3.update2(msg)
237
238
239 needed := sm3.Size()
240 if cap(in)-len(in) < needed {
241 newIn := make([]byte, len(in), len(in)+needed)
242 copy(newIn, in)
243 in = newIn
244 }
245 out := in[len(in) : len(in)+needed]
246 for i := 0; i < 8; i++ {
247 binary.BigEndian.PutUint32(out[i*4:], digest[i])
248 }
249 return out
250
251 }
252
253 func Sm3Sum(data []byte) []byte {
254 var sm3 SM3
255
256 sm3.Reset()
257 _, _ = sm3.Write(data)
258 return sm3.Sum(nil)
259 }
260
View as plain text