github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/crypto/x11/shavite/shavite.go (about) 1 // Use of this source code is governed by an ISC 2 // license that can be found in the LICENSE file. 3 4 package shavite 5 6 import ( 7 "fmt" 8 9 "github.com/wtc/go-wtc/crypto/hash" 10 "github.com/wtc/go-wtc/crypto/x11/aesr" 11 ) 12 13 // HashSize holds the size of a hash in bytes. 14 const HashSize = int(64) 15 16 // BlockSize holds the size of a block in bytes. 17 const BlockSize = uintptr(128) 18 19 //////////////// 20 21 type digest struct { 22 ptr uintptr 23 24 h [16]uint32 25 c [4]uint32 26 27 b [BlockSize]byte 28 } 29 30 // New returns a new digest to compute a SHAVITE512 hash. 31 func New() hash.Digest { 32 ref := &digest{} 33 ref.Reset() 34 return ref 35 } 36 37 //////////////// 38 39 // Reset resets the digest to its initial state. 40 func (ref *digest) Reset() { 41 ref.ptr = 0 42 copy(ref.h[:], kInit[:]) 43 ref.c[0], ref.c[1] = 0, 0 44 ref.c[2], ref.c[3] = 0, 0 45 } 46 47 // Sum appends the current hash to dst and returns the result 48 // as a slice. It does not change the underlying hash state. 49 func (ref *digest) Sum(dst []byte) []byte { 50 dgt := *ref 51 hsh := [64]byte{} 52 dgt.Close(hsh[:], 0, 0) 53 return append(dst, hsh[:]...) 54 } 55 56 // Write more data to the running hash, never returns an error. 57 func (ref *digest) Write(src []byte) (int, error) { 58 sln := uintptr(len(src)) 59 fln := len(src) 60 ptr := ref.ptr 61 62 for sln > 0 { 63 cln := BlockSize - ptr 64 65 if cln > sln { 66 cln = sln 67 } 68 sln -= cln 69 70 copy(ref.b[ptr:], src[:cln]) 71 src = src[cln:] 72 ptr += cln 73 74 if ptr == BlockSize { 75 ref.c[0] += 1024 76 if ref.c[0] == 0 { 77 ref.c[1] += 1 78 if ref.c[1] == 0 { 79 ref.c[2] += 1 80 if ref.c[2] == 0 { 81 ref.c[3] += 1 82 } 83 } 84 } 85 86 ref.compress() 87 ptr = 0 88 } 89 } 90 91 ref.ptr = ptr 92 return fln, nil 93 } 94 95 // Close the digest by writing the last bits and storing the hash 96 // in dst. This prepares the digest for reuse by calling reset. A call 97 // to Close with a dst that is smaller then HashSize will return an error. 98 func (ref *digest) Close(dst []byte, bits uint8, bcnt uint8) error { 99 if ln := len(dst); HashSize > ln { 100 return fmt.Errorf("Shavite Close: dst min length: %d, got %d", HashSize, ln) 101 } 102 103 var cnt [4]uint32 104 105 ptr := ref.ptr 106 buf := ref.b[:] 107 108 ref.c[0] += uint32(ptr<<3) + uint32(bcnt) 109 cnt[0] = ref.c[0] 110 cnt[1] = ref.c[1] 111 cnt[2] = ref.c[2] 112 cnt[3] = ref.c[3] 113 114 z := uint8(0x80) >> bcnt 115 z = uint8((bits & -z) | z) 116 117 if (ptr == 0) && (bcnt == 0) { 118 buf[0] = 0x80 119 memset(buf[1:110], 0) 120 ref.c[0], ref.c[1] = 0, 0 121 ref.c[2], ref.c[3] = 0, 0 122 } else if ptr < 110 { 123 buf[ptr] = z 124 ptr += 1 125 memset(buf[ptr:(ptr+(110-ptr))], 0) 126 } else { 127 buf[ptr] = z 128 ptr += 1 129 memset(buf[ptr:(ptr+(128-ptr))], 0) 130 131 ref.compress() 132 memset(buf[:], 0) 133 ref.c[0], ref.c[1] = 0, 0 134 ref.c[2], ref.c[3] = 0, 0 135 } 136 137 encUInt32le(buf[110:], cnt[0]) 138 encUInt32le(buf[114:], cnt[1]) 139 encUInt32le(buf[118:], cnt[2]) 140 encUInt32le(buf[122:], cnt[3]) 141 142 buf[126] = 0 143 buf[127] = 2 144 145 ref.compress() 146 147 for u := uintptr(0); u < 16; u++ { 148 encUInt32le(dst[(u<<2):], ref.h[u]) 149 } 150 151 ref.Reset() 152 return nil 153 } 154 155 // Size returns the number of bytes required to store the hash. 156 func (*digest) Size() int { 157 return HashSize 158 } 159 160 // BlockSize returns the block size of the hash. 161 func (*digest) BlockSize() int { 162 return int(BlockSize) 163 } 164 165 //////////////// 166 167 func memset(dst []byte, src byte) { 168 for i := range dst { 169 dst[i] = src 170 } 171 } 172 173 func decUInt32le(src []byte) uint32 { 174 return (uint32(src[0]) | 175 uint32(src[1])<<8 | 176 uint32(src[2])<<16 | 177 uint32(src[3])<<24) 178 } 179 180 func encUInt32le(dst []uint8, src uint32) { 181 dst[0] = uint8(src) 182 dst[1] = uint8(src >> 8) 183 dst[2] = uint8(src >> 16) 184 dst[3] = uint8(src >> 24) 185 } 186 187 func (ref *digest) compress() { 188 var p0, p1, p2, p3, p4, p5, p6, p7 uint32 189 var p8, p9, pA, pB, pC, pD, pE, pF uint32 190 var t0, t1, t2, t3 uint32 191 var rk [448]uint32 192 193 for i := uintptr(0); i < 32; i++ { 194 rk[i] = decUInt32le(ref.b[(i * 4):]) 195 //rk[i] = decUInt32be(ref.b[(i * 4):]) 196 } 197 198 idx := uintptr(32) 199 for idx < 448 { 200 for s := uintptr(0); s < 4; s++ { 201 t0 = rk[idx-31] 202 t1 = rk[idx-30] 203 t2 = rk[idx-29] 204 t3 = rk[idx-32] 205 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 206 rk[idx+0] = t0 ^ rk[idx-4] 207 rk[idx+1] = t1 ^ rk[idx-3] 208 rk[idx+2] = t2 ^ rk[idx-2] 209 rk[idx+3] = t3 ^ rk[idx-1] 210 if idx == 32 { 211 rk[32] ^= ref.c[0] 212 rk[33] ^= ref.c[1] 213 rk[34] ^= ref.c[2] 214 rk[35] ^= uint32(^ref.c[3]) 215 } else if idx == 440 { 216 rk[440] ^= ref.c[1] 217 rk[441] ^= ref.c[0] 218 rk[442] ^= ref.c[3] 219 rk[443] ^= uint32(^ref.c[2]) 220 } 221 idx += 4 222 223 t0 = rk[idx-31] 224 t1 = rk[idx-30] 225 t2 = rk[idx-29] 226 t3 = rk[idx-32] 227 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 228 rk[idx+0] = t0 ^ rk[idx-4] 229 rk[idx+1] = t1 ^ rk[idx-3] 230 rk[idx+2] = t2 ^ rk[idx-2] 231 rk[idx+3] = t3 ^ rk[idx-1] 232 if idx == 164 { 233 rk[164] ^= ref.c[3] 234 rk[165] ^= ref.c[2] 235 rk[166] ^= ref.c[1] 236 rk[167] ^= uint32(^ref.c[0]) 237 } else if idx == 316 { 238 rk[316] ^= ref.c[2] 239 rk[317] ^= ref.c[3] 240 rk[318] ^= ref.c[0] 241 rk[319] ^= uint32(^ref.c[1]) 242 } 243 idx += 4 244 } 245 246 if idx != 448 { 247 for s := uintptr(0); s < 8; s++ { 248 rk[idx+0] = rk[idx-32] ^ rk[idx-7] 249 rk[idx+1] = rk[idx-31] ^ rk[idx-6] 250 rk[idx+2] = rk[idx-30] ^ rk[idx-5] 251 rk[idx+3] = rk[idx-29] ^ rk[idx-4] 252 idx += 4 253 } 254 } 255 } 256 257 p0 = ref.h[0x0] 258 p1 = ref.h[0x1] 259 p2 = ref.h[0x2] 260 p3 = ref.h[0x3] 261 p4 = ref.h[0x4] 262 p5 = ref.h[0x5] 263 p6 = ref.h[0x6] 264 p7 = ref.h[0x7] 265 p8 = ref.h[0x8] 266 p9 = ref.h[0x9] 267 pA = ref.h[0xA] 268 pB = ref.h[0xB] 269 pC = ref.h[0xC] 270 pD = ref.h[0xD] 271 pE = ref.h[0xE] 272 pF = ref.h[0xF] 273 274 idx = 0 275 for r := uint32(0); r < 14; r++ { 276 t0 = p4 ^ rk[idx+0] 277 t1 = p5 ^ rk[idx+1] 278 t2 = p6 ^ rk[idx+2] 279 t3 = p7 ^ rk[idx+3] 280 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 281 t0 ^= rk[idx+4] 282 t1 ^= rk[idx+5] 283 t2 ^= rk[idx+6] 284 t3 ^= rk[idx+7] 285 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 286 t0 ^= rk[idx+8] 287 t1 ^= rk[idx+9] 288 t2 ^= rk[idx+10] 289 t3 ^= rk[idx+11] 290 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 291 t0 ^= rk[idx+12] 292 t1 ^= rk[idx+13] 293 t2 ^= rk[idx+14] 294 t3 ^= rk[idx+15] 295 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 296 p0 ^= t0 297 p1 ^= t1 298 p2 ^= t2 299 p3 ^= t3 300 301 idx += 16 302 303 t0 = pC ^ rk[idx+0] 304 t1 = pD ^ rk[idx+1] 305 t2 = pE ^ rk[idx+2] 306 t3 = pF ^ rk[idx+3] 307 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 308 t0 ^= rk[idx+4] 309 t1 ^= rk[idx+5] 310 t2 ^= rk[idx+6] 311 t3 ^= rk[idx+7] 312 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 313 t0 ^= rk[idx+8] 314 t1 ^= rk[idx+9] 315 t2 ^= rk[idx+10] 316 t3 ^= rk[idx+11] 317 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 318 t0 ^= rk[idx+12] 319 t1 ^= rk[idx+13] 320 t2 ^= rk[idx+14] 321 t3 ^= rk[idx+15] 322 t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3) 323 p8 ^= t0 324 p9 ^= t1 325 pA ^= t2 326 pB ^= t3 327 328 idx += 16 329 330 t0 = pC 331 pC = p8 332 p8 = p4 333 p4 = p0 334 p0 = t0 335 336 t0 = pD 337 pD = p9 338 p9 = p5 339 p5 = p1 340 p1 = t0 341 342 t0 = pE 343 pE = pA 344 pA = p6 345 p6 = p2 346 p2 = t0 347 348 t0 = pF 349 pF = pB 350 pB = p7 351 p7 = p3 352 p3 = t0 353 } 354 355 ref.h[0x0] ^= p0 356 ref.h[0x1] ^= p1 357 ref.h[0x2] ^= p2 358 ref.h[0x3] ^= p3 359 ref.h[0x4] ^= p4 360 ref.h[0x5] ^= p5 361 ref.h[0x6] ^= p6 362 ref.h[0x7] ^= p7 363 ref.h[0x8] ^= p8 364 ref.h[0x9] ^= p9 365 ref.h[0xA] ^= pA 366 ref.h[0xB] ^= pB 367 ref.h[0xC] ^= pC 368 ref.h[0xD] ^= pD 369 ref.h[0xE] ^= pE 370 ref.h[0xF] ^= pF 371 } 372 373 //////////////// 374 375 var kInit = [16]uint32{ 376 uint32(0x72FCCDD8), uint32(0x79CA4727), 377 uint32(0x128A077B), uint32(0x40D55AEC), 378 uint32(0xD1901A06), uint32(0x430AE307), 379 uint32(0xB29F5CD1), uint32(0xDF07FBFC), 380 uint32(0x8E45D73D), uint32(0x681AB538), 381 uint32(0xBDE86578), uint32(0xDD577E47), 382 uint32(0xE275EADE), uint32(0x502D9FCD), 383 uint32(0xB9357178), uint32(0x022A4B9A), 384 }