github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/sm3soft/sm3_soft.go (about) 1 // Copyright 2022 s1ren@github.com/hxx258456. 2 3 /* 4 sm3soft 是sm3的纯软实现,基于tjfoc国密算法库`tjfoc/gmsm`做了少量修改。 5 对应版权声明: thrid_licenses/github.com/tjfoc/gmsm/版权声明 6 */ 7 8 package sm3soft 9 10 /* 11 sm3/sm3.go SM3实现 12 */ 13 14 import ( 15 "encoding/binary" 16 "hash" 17 ) 18 19 // Size SM3散列结果的字节长度,对应bit长度为256位 20 const Size = 32 21 22 // BlockSize SM3散列时一个Block的字节长度,对应bit长度为512位 23 const BlockSize = 64 24 25 type SM3 struct { 26 digest [8]uint32 // digest represents the partial evaluation of V 27 length uint64 // length of the message 28 unhandleMsg []byte // uint8 // 29 } 30 31 // 布尔函数FF,SM3压缩函数内部迭代在[0,15]区间时使用 32 func (sm3 *SM3) ff0(x, y, z uint32) uint32 { return x ^ y ^ z } 33 34 // 布尔函数FF,SM3压缩函数内部迭代在[16,63]区间时使用 35 func (sm3 *SM3) ff1(x, y, z uint32) uint32 { return (x & y) | (x & z) | (y & z) } 36 37 // 布尔函数GG,SM3压缩函数内部迭代在[0,15]区间时使用 38 func (sm3 *SM3) gg0(x, y, z uint32) uint32 { return x ^ y ^ z } 39 40 // 布尔函数GG,SM3压缩函数内部迭代在[16,63]区间时使用 41 func (sm3 *SM3) gg1(x, y, z uint32) uint32 { return (x & y) | (^x & z) } 42 43 // 置换函数P0 44 func (sm3 *SM3) p0(x uint32) uint32 { return x ^ sm3.leftRotate(x, 9) ^ sm3.leftRotate(x, 17) } 45 46 // 置换函数P1 47 func (sm3 *SM3) p1(x uint32) uint32 { return x ^ sm3.leftRotate(x, 15) ^ sm3.leftRotate(x, 23) } 48 49 // 循环左移 50 func (sm3 *SM3) leftRotate(x uint32, i uint32) uint32 { return x<<(i%32) | x>>(32-i%32) } 51 52 func (sm3 *SM3) pad() []byte { 53 msg := sm3.unhandleMsg 54 msg = append(msg, 0x80) // Append '1' 55 blockSize := 64 // Append until the resulting message length (in bits) is congruent to 448 (mod 512) 56 for len(msg)%blockSize != 56 { 57 msg = append(msg, 0x00) 58 } 59 // append message length 60 msg = append(msg, uint8(sm3.length>>56&0xff)) 61 msg = append(msg, uint8(sm3.length>>48&0xff)) 62 msg = append(msg, uint8(sm3.length>>40&0xff)) 63 msg = append(msg, uint8(sm3.length>>32&0xff)) 64 msg = append(msg, uint8(sm3.length>>24&0xff)) 65 msg = append(msg, uint8(sm3.length>>16&0xff)) 66 msg = append(msg, uint8(sm3.length>>8&0xff)) 67 msg = append(msg, uint8(sm3.length>>0&0xff)) 68 69 if len(msg)%64 != 0 { 70 panic("------SM3 Pad: error msgLen =") 71 } 72 return msg 73 } 74 75 func (sm3 *SM3) update(msg []byte) { 76 var w [68]uint32 77 var w1 [64]uint32 78 79 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] 80 for len(msg) >= 64 { 81 for i := 0; i < 16; i++ { 82 w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)]) 83 } 84 for i := 16; i < 68; i++ { 85 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] 86 } 87 for i := 0; i < 64; i++ { 88 w1[i] = w[i] ^ w[i+4] 89 } 90 A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h 91 for i := 0; i < 16; i++ { 92 SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7) 93 SS2 := SS1 ^ sm3.leftRotate(A, 12) 94 TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i] 95 TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i] 96 D = C 97 C = sm3.leftRotate(B, 9) 98 B = A 99 A = TT1 100 H = G 101 G = sm3.leftRotate(F, 19) 102 F = E 103 E = sm3.p0(TT2) 104 } 105 for i := 16; i < 64; i++ { 106 SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7) 107 SS2 := SS1 ^ sm3.leftRotate(A, 12) 108 TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i] 109 TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i] 110 D = C 111 C = sm3.leftRotate(B, 9) 112 B = A 113 A = TT1 114 H = G 115 G = sm3.leftRotate(F, 19) 116 F = E 117 E = sm3.p0(TT2) 118 } 119 a ^= A 120 b ^= B 121 c ^= C 122 d ^= D 123 e ^= E 124 f ^= F 125 g ^= G 126 h ^= H 127 msg = msg[64:] 128 } 129 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 130 } 131 func (sm3 *SM3) update2(msg []byte) [8]uint32 { 132 var w [68]uint32 133 var w1 [64]uint32 134 135 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] 136 for len(msg) >= 64 { 137 for i := 0; i < 16; i++ { 138 w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)]) 139 } 140 for i := 16; i < 68; i++ { 141 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] 142 } 143 for i := 0; i < 64; i++ { 144 w1[i] = w[i] ^ w[i+4] 145 } 146 A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h 147 for i := 0; i < 16; i++ { 148 SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7) 149 SS2 := SS1 ^ sm3.leftRotate(A, 12) 150 TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i] 151 TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i] 152 D = C 153 C = sm3.leftRotate(B, 9) 154 B = A 155 A = TT1 156 H = G 157 G = sm3.leftRotate(F, 19) 158 F = E 159 E = sm3.p0(TT2) 160 } 161 for i := 16; i < 64; i++ { 162 SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7) 163 SS2 := SS1 ^ sm3.leftRotate(A, 12) 164 TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i] 165 TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i] 166 D = C 167 C = sm3.leftRotate(B, 9) 168 B = A 169 A = TT1 170 H = G 171 G = sm3.leftRotate(F, 19) 172 F = E 173 E = sm3.p0(TT2) 174 } 175 a ^= A 176 b ^= B 177 c ^= C 178 d ^= D 179 e ^= E 180 f ^= F 181 g ^= G 182 h ^= H 183 msg = msg[64:] 184 } 185 var digest [8]uint32 186 digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7] = a, b, c, d, e, f, g, h 187 return digest 188 } 189 190 // New 创建哈希计算实例 191 func New() hash.Hash { 192 var sm3 SM3 193 194 sm3.Reset() 195 return &sm3 196 } 197 198 // BlockSize returns the hash's underlying block size. 199 // The Write method must be able to accept any amount 200 // of data, but it may operate more efficiently if all writes 201 // are a multiple of the block size. 202 func (sm3 *SM3) BlockSize() int { return BlockSize } 203 204 // Size returns the number of bytes Sum will return. 205 func (sm3 *SM3) Size() int { return Size } 206 207 // Reset clears the internal state by zeroing bytes in the state buffer. 208 // This can be skipped for a newly-created hash state; the default zero-allocated state is correct. 209 func (sm3 *SM3) Reset() { 210 // Reset digest 211 sm3.digest[0] = 0x7380166f 212 sm3.digest[1] = 0x4914b2b9 213 sm3.digest[2] = 0x172442d7 214 sm3.digest[3] = 0xda8a0600 215 sm3.digest[4] = 0xa96f30bc 216 sm3.digest[5] = 0x163138aa 217 sm3.digest[6] = 0xe38dee4d 218 sm3.digest[7] = 0xb0fb0e4e 219 220 sm3.length = 0 // Reset numberic states 221 sm3.unhandleMsg = []byte{} 222 } 223 224 // Write (via the embedded io.Writer interface) adds more data to the running hash. 225 // It never returns an error. 226 func (sm3 *SM3) Write(p []byte) (int, error) { 227 toWrite := len(p) 228 sm3.length += uint64(len(p) * 8) 229 msg := append(sm3.unhandleMsg, p...) 230 nblocks := len(msg) / sm3.BlockSize() 231 sm3.update(msg) 232 // Update unhandleMsg 233 sm3.unhandleMsg = msg[nblocks*sm3.BlockSize():] 234 235 return toWrite, nil 236 } 237 238 // Sum 返回SM3哈希算法摘要值 239 // Sum appends the current hash to b and returns the resulting slice. 240 // It does not change the underlying hash state. 241 func (sm3 *SM3) Sum(in []byte) []byte { 242 _, _ = sm3.Write(in) 243 msg := sm3.pad() 244 //Finalize 245 digest := sm3.update2(msg) 246 247 // save hash to in 248 needed := sm3.Size() 249 if cap(in)-len(in) < needed { 250 newIn := make([]byte, len(in), len(in)+needed) 251 copy(newIn, in) 252 in = newIn 253 } 254 out := in[len(in) : len(in)+needed] 255 for i := 0; i < 8; i++ { 256 binary.BigEndian.PutUint32(out[i*4:], digest[i]) 257 } 258 return out 259 260 } 261 262 func Sm3Sum(data []byte) []byte { 263 var sm3 SM3 264 265 sm3.Reset() 266 _, _ = sm3.Write(data) 267 return sm3.Sum(nil) 268 }