github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/crypto/x11/echo/echo.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 echo 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 = uintptr(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 [8][2]uint64 25 c [4]uint32 26 27 b [BlockSize]byte 28 } 29 30 // New returns a new digest compute a ECHO512 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 43 ref.h[0][0] = uint64(8 * HashSize) 44 ref.h[0][1] = 0 45 ref.h[1][0] = uint64(8 * HashSize) 46 ref.h[1][1] = 0 47 ref.h[2][0] = uint64(8 * HashSize) 48 ref.h[2][1] = 0 49 ref.h[3][0] = uint64(8 * HashSize) 50 ref.h[3][1] = 0 51 ref.h[4][0] = uint64(8 * HashSize) 52 ref.h[4][1] = 0 53 ref.h[5][0] = uint64(8 * HashSize) 54 ref.h[5][1] = 0 55 ref.h[6][0] = uint64(8 * HashSize) 56 ref.h[6][1] = 0 57 ref.h[7][0] = uint64(8 * HashSize) 58 ref.h[7][1] = 0 59 60 memset32(ref.c[:], 0) 61 } 62 63 // Sum appends the current hash to dst and returns the result 64 // as a slice. It does not change the underlying hash state. 65 func (ref *digest) Sum(dst []byte) []byte { 66 dgt := *ref 67 hsh := [64]byte{} 68 dgt.Close(hsh[:], 0, 0) 69 return append(dst, hsh[:]...) 70 } 71 72 // Write more data to the running hash, never returns an error. 73 func (ref *digest) Write(src []byte) (int, error) { 74 sln := uintptr(len(src)) 75 fln := len(src) 76 ptr := ref.ptr 77 78 if sln < (BlockSize - ptr) { 79 copy(ref.b[ptr:], src) 80 ref.ptr += sln 81 return int(sln), nil 82 } 83 84 for sln > 0 { 85 cln := BlockSize - ptr 86 87 if cln > sln { 88 cln = sln 89 } 90 sln -= cln 91 92 copy(ref.b[ptr:], src[:cln]) 93 src = src[cln:] 94 ptr += cln 95 96 if ptr == BlockSize { 97 ref.c[0] += 1024 98 if ref.c[0] < 1024 { 99 ref.c[1] += 1 100 if ref.c[1] == 0 { 101 ref.c[2] += 1 102 if ref.c[2] == 0 { 103 ref.c[3] += 1 104 } 105 } 106 } 107 108 compress(ref) 109 ptr = 0 110 } 111 } 112 113 ref.ptr = ptr 114 return fln, nil 115 } 116 117 // Close the digest by writing the last bits and storing the hash 118 // in dst. This prepares the digest for reuse by calling reset. A call 119 // to Close with a dst that is smaller then HashSize will return an error. 120 func (ref *digest) Close(dst []byte, bits uint8, bcnt uint8) error { 121 if ln := len(dst); HashSize > uintptr(ln) { 122 return fmt.Errorf("Echo Close: dst min length: %d, got %d", HashSize, ln) 123 } 124 125 ptr := ref.ptr 126 buf := ref.b[:] 127 128 eln := uint32(ptr<<3) + uint32(bcnt) 129 130 ref.c[0] += eln 131 if ref.c[0] < eln { 132 ref.c[1] += 1 133 if ref.c[1] == 0 { 134 ref.c[2] += 1 135 if ref.c[2] == 0 { 136 ref.c[3] += 1 137 } 138 } 139 } 140 141 var tmp [64]uint8 142 encUInt32le(tmp[:], ref.c[0]) 143 encUInt32le(tmp[4:], ref.c[1]) 144 encUInt32le(tmp[8:], ref.c[2]) 145 encUInt32le(tmp[12:], ref.c[3]) 146 147 if eln == 0 { 148 memset32(ref.c[:], 0) 149 } 150 151 { 152 off := uint8(0x80) >> bcnt 153 buf[ptr] = uint8((bits & -off) | off) 154 } 155 156 ptr += 1 157 memset8(buf[ptr:], 0) 158 159 if ptr > (BlockSize - 18) { 160 compress(ref) 161 memset8(buf[:], 0) 162 memset32(ref.c[:], 0) 163 } 164 165 encUInt16le(buf[(BlockSize-18):], uint16(16<<5)) 166 copy(buf[(BlockSize-16):], tmp[:]) 167 compress(ref) 168 169 h := ref.h[:] 170 for x := uintptr(0); x < 4; x++ { 171 for y := uintptr(0); y < 2; y++ { 172 encUInt64le(dst[(((x*2)+y)*8):], h[x][y]) 173 } 174 } 175 176 ref.Reset() 177 return nil 178 } 179 180 // Size returns the number of bytes required to store the hash. 181 func (*digest) Size() int { 182 return int(HashSize) 183 } 184 185 // BlockSize returns the block size of the hash. 186 func (*digest) BlockSize() int { 187 return int(BlockSize) 188 } 189 190 //////////////// 191 192 func memset8(dst []byte, src byte) { 193 for i := range dst { 194 dst[i] = src 195 } 196 } 197 198 func memset32(dst []uint32, src uint32) { 199 for i := range dst { 200 dst[i] = src 201 } 202 } 203 204 func compress(ref *digest) { 205 var w [16][2]uint64 206 207 k0 := ref.c[0] 208 k1 := ref.c[1] 209 k2 := ref.c[2] 210 k3 := ref.c[3] 211 212 for i := uintptr(0); i < 8; i++ { 213 w[i][0] = ref.h[i][0] 214 w[i+8][0] = decUInt64le(ref.b[(16 * i):]) 215 w[i][1] = ref.h[i][1] 216 w[i+8][1] = decUInt64le(ref.b[((16 * i) + 8):]) 217 } 218 219 var a0, a1, a2 uint64 220 var b0, b1, b2 uint64 221 222 var w0, w1, w2, w3 uint64 223 224 var x0, x1, x2, x3 uint32 225 var y0, y1, y2, y3 uint32 226 227 for u := uintptr(0); u < 10; u++ { 228 for n := uintptr(0); n < 16; n++ { 229 x0 = uint32(w[n][0]) 230 x1 = uint32(w[n][0] >> 32) 231 x2 = uint32(w[n][1]) 232 x3 = uint32(w[n][1] >> 32) 233 234 y0, y1, y2, y3 = aesr.Round32ble( 235 x0, x1, x2, x3, 236 k0, k1, k2, k3, 237 ) 238 x0, x1, x2, x3 = aesr.Round32ble( 239 y0, y1, y2, y3, 240 0, 0, 0, 0, 241 ) 242 243 w[n][0] = uint64(x0) | (uint64(x1) << 32) 244 w[n][1] = uint64(x2) | (uint64(x3) << 32) 245 246 k0 += 1 247 if k0 == 0 { 248 k1 += 1 249 if k1 == 0 { 250 k2 += 1 251 if k2 == 0 { 252 k3 += 1 253 } 254 } 255 } 256 } 257 258 a0 = w[1][0] 259 w[1][0] = w[5][0] 260 w[5][0] = w[9][0] 261 w[9][0] = w[13][0] 262 w[13][0] = a0 263 264 a0 = w[1][1] 265 w[1][1] = w[5][1] 266 w[5][1] = w[9][1] 267 w[9][1] = w[13][1] 268 w[13][1] = a0 269 270 a0 = w[2][0] 271 w[2][0] = w[10][0] 272 w[10][0] = a0 273 274 a0 = w[6][0] 275 w[6][0] = w[14][0] 276 w[14][0] = a0 277 278 a0 = w[2][1] 279 w[2][1] = w[10][1] 280 w[10][1] = a0 281 282 a0 = w[6][1] 283 w[6][1] = w[14][1] 284 w[14][1] = a0 285 286 a0 = w[15][0] 287 w[15][0] = w[11][0] 288 w[11][0] = w[7][0] 289 w[7][0] = w[3][0] 290 w[3][0] = a0 291 292 a0 = w[15][1] 293 w[15][1] = w[11][1] 294 w[11][1] = w[7][1] 295 w[7][1] = w[3][1] 296 w[3][1] = a0 297 298 for n := uintptr(0); n < 2; n++ { 299 w0 = w[0][n] 300 w1 = w[1][n] 301 w2 = w[2][n] 302 w3 = w[3][n] 303 a0 = w0 ^ w1 304 a1 = w1 ^ w2 305 a2 = w2 ^ w3 306 b0 = (((a0&uint64(0x8080808080808080))>>7)*27 ^ 307 ((a0 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 308 b1 = (((a1&uint64(0x8080808080808080))>>7)*27 ^ 309 ((a1 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 310 b2 = (((a2&uint64(0x8080808080808080))>>7)*27 ^ 311 ((a2 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 312 w[0][n] = b0 ^ a1 ^ w3 313 w[1][n] = b1 ^ w0 ^ a2 314 w[2][n] = b2 ^ a0 ^ w3 315 w[3][n] = b0 ^ b1 ^ b2 ^ a0 ^ w2 316 317 w0 = w[4][n] 318 w1 = w[5][n] 319 w2 = w[6][n] 320 w3 = w[7][n] 321 a0 = w0 ^ w1 322 a1 = w1 ^ w2 323 a2 = w2 ^ w3 324 b0 = (((a0&uint64(0x8080808080808080))>>7)*27 ^ 325 ((a0 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 326 b1 = (((a1&uint64(0x8080808080808080))>>7)*27 ^ 327 ((a1 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 328 b2 = (((a2&uint64(0x8080808080808080))>>7)*27 ^ 329 ((a2 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 330 w[4][n] = b0 ^ a1 ^ w3 331 w[5][n] = b1 ^ w0 ^ a2 332 w[6][n] = b2 ^ a0 ^ w3 333 w[7][n] = b0 ^ b1 ^ b2 ^ a0 ^ w2 334 335 w0 = w[8][n] 336 w1 = w[9][n] 337 w2 = w[10][n] 338 w3 = w[11][n] 339 a0 = w0 ^ w1 340 a1 = w1 ^ w2 341 a2 = w2 ^ w3 342 b0 = (((a0&uint64(0x8080808080808080))>>7)*27 ^ 343 ((a0 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 344 b1 = (((a1&uint64(0x8080808080808080))>>7)*27 ^ 345 ((a1 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 346 b2 = (((a2&uint64(0x8080808080808080))>>7)*27 ^ 347 ((a2 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 348 w[8][n] = b0 ^ a1 ^ w3 349 w[9][n] = b1 ^ w0 ^ a2 350 w[10][n] = b2 ^ a0 ^ w3 351 w[11][n] = b0 ^ b1 ^ b2 ^ a0 ^ w2 352 353 w0 = w[12][n] 354 w1 = w[13][n] 355 w2 = w[14][n] 356 w3 = w[15][n] 357 a0 = w0 ^ w1 358 a1 = w1 ^ w2 359 a2 = w2 ^ w3 360 b0 = (((a0&uint64(0x8080808080808080))>>7)*27 ^ 361 ((a0 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 362 b1 = (((a1&uint64(0x8080808080808080))>>7)*27 ^ 363 ((a1 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 364 b2 = (((a2&uint64(0x8080808080808080))>>7)*27 ^ 365 ((a2 & uint64(0x7F7F7F7F7F7F7F7F)) << 1)) 366 w[12][n] = b0 ^ a1 ^ w3 367 w[13][n] = b1 ^ w0 ^ a2 368 w[14][n] = b2 ^ a0 ^ w3 369 w[15][n] = b0 ^ b1 ^ b2 ^ a0 ^ w2 370 } 371 } 372 373 h := ref.h[:] 374 for x := uintptr(0); x < 8; x++ { 375 for y := uintptr(0); y < 2; y++ { 376 h[x][y] ^= decUInt64le(ref.b[(((x*2)+y)*8):]) ^ w[x][y] ^ w[x+8][y] 377 } 378 } 379 } 380 381 func decUInt64le(src []byte) uint64 { 382 return (uint64(src[0]) | 383 uint64(src[1])<<8 | 384 uint64(src[2])<<16 | 385 uint64(src[3])<<24 | 386 uint64(src[4])<<32 | 387 uint64(src[5])<<40 | 388 uint64(src[6])<<48 | 389 uint64(src[7])<<56) 390 } 391 392 func encUInt16le(dst []byte, src uint16) { 393 dst[0] = uint8(src) 394 dst[1] = uint8(src >> 8) 395 } 396 397 func encUInt32le(dst []uint8, src uint32) { 398 dst[0] = uint8(src) 399 dst[1] = uint8(src >> 8) 400 dst[2] = uint8(src >> 16) 401 dst[3] = uint8(src >> 24) 402 } 403 404 func encUInt64le(dst []byte, src uint64) { 405 dst[0] = uint8(src) 406 dst[1] = uint8(src >> 8) 407 dst[2] = uint8(src >> 16) 408 dst[3] = uint8(src >> 24) 409 dst[4] = uint8(src >> 32) 410 dst[5] = uint8(src >> 40) 411 dst[6] = uint8(src >> 48) 412 dst[7] = uint8(src >> 56) 413 }