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  }