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  }