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