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  }