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