github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/cryptonight/keccak.go (about)

     1  // Copyright 2017-2018 DERO Project. All rights reserved.
     2  // Use of this source code in any form is governed by RESEARCH license.
     3  // license can be found in the LICENSE file.
     4  // GPG: 0F39 E425 8C65 3947 702A  8234 08B2 0360 A03A 9DE8
     5  //
     6  //
     7  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
     8  // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     9  // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
    10  // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    11  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    12  // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    13  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    14  // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    15  // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    16  
    17  // TODO keccak is available in 3 of our packages we need to merge them when the alpha version is out
    18  // Package keccak implements the Keccak (SHA-3) hash algorithm.
    19  // http://keccak.noekeon.org / FIPS 202 draft.
    20  package cryptonight
    21  
    22  // import "fmt"
    23  import "hash"
    24  
    25  const (
    26  	domainNone  = 1
    27  	domainSHA3  = 0x06
    28  	domainSHAKE = 0x1f
    29  )
    30  
    31  const rounds = 24
    32  
    33  var roundConstants = []uint64{
    34  	0x0000000000000001, 0x0000000000008082,
    35  	0x800000000000808A, 0x8000000080008000,
    36  	0x000000000000808B, 0x0000000080000001,
    37  	0x8000000080008081, 0x8000000000008009,
    38  	0x000000000000008A, 0x0000000000000088,
    39  	0x0000000080008009, 0x000000008000000A,
    40  	0x000000008000808B, 0x800000000000008B,
    41  	0x8000000000008089, 0x8000000000008003,
    42  	0x8000000000008002, 0x8000000000000080,
    43  	0x000000000000800A, 0x800000008000000A,
    44  	0x8000000080008081, 0x8000000000008080,
    45  	0x0000000080000001, 0x8000000080008008,
    46  }
    47  
    48  type keccak struct {
    49  	S         [25]uint64
    50  	size      int
    51  	blockSize int
    52  	buf       []byte
    53  	domain    byte
    54  }
    55  
    56  func newKeccak(capacity, output int, domain byte) hash.Hash {
    57  	var h keccak
    58  	h.size = output / 8
    59  	h.blockSize = (200 - capacity/8)
    60  	h.domain = domain
    61  	return &h
    62  }
    63  
    64  func New224() hash.Hash {
    65  	return newKeccak(224*2, 224, domainNone)
    66  }
    67  
    68  func New256() hash.Hash {
    69  	return newKeccak(256*2, 256, domainNone)
    70  }
    71  
    72  func New384() hash.Hash {
    73  	return newKeccak(384*2, 384, domainNone)
    74  }
    75  
    76  func New512() hash.Hash {
    77  	return newKeccak(512*2, 512, domainNone)
    78  }
    79  
    80  func (k *keccak) Write(b []byte) (int, error) {
    81  	n := len(b)
    82  
    83  	if len(k.buf) > 0 {
    84  		x := k.blockSize - len(k.buf)
    85  		if x > len(b) {
    86  			x = len(b)
    87  		}
    88  		k.buf = append(k.buf, b[:x]...)
    89  		b = b[x:]
    90  
    91  		if len(k.buf) < k.blockSize {
    92  			return n, nil
    93  		}
    94  
    95  		k.absorb(k.buf)
    96  		k.buf = nil
    97  	}
    98  
    99  	for len(b) >= k.blockSize {
   100  		k.absorb(b[:k.blockSize])
   101  		b = b[k.blockSize:]
   102  	}
   103  
   104  	k.buf = b
   105  
   106  	return n, nil
   107  }
   108  
   109  func (k0 *keccak) Sum(b []byte) []byte {
   110  	k := *k0
   111  	k.final()
   112  	return k.squeeze(b)
   113  }
   114  
   115  func (k *keccak) Reset() {
   116  	for i := range k.S {
   117  		k.S[i] = 0
   118  	}
   119  	k.buf = nil
   120  }
   121  
   122  func (k *keccak) Size() int {
   123  	return k.size
   124  }
   125  
   126  func (k *keccak) BlockSize() int {
   127  	return k.blockSize
   128  }
   129  
   130  func (k *keccak) absorb(block []byte) {
   131  	if len(block) != k.blockSize {
   132  		panic("absorb() called with invalid block size")
   133  	}
   134  
   135  	for i := 0; i < k.blockSize/8; i++ {
   136  		k.S[i] ^= uint64le(block[i*8:])
   137  	}
   138  	keccakf(&k.S)
   139  }
   140  
   141  func (k *keccak) pad(block []byte) []byte {
   142  
   143  	padded := make([]byte, k.blockSize)
   144  
   145  	copy(padded, k.buf)
   146  	padded[len(k.buf)] = k.domain
   147  	padded[len(padded)-1] |= 0x80
   148  
   149  	return padded
   150  }
   151  
   152  func (k *keccak) final() {
   153  	last := k.pad(k.buf)
   154  	k.absorb(last)
   155  }
   156  
   157  func (k *keccak) squeeze(b []byte) []byte {
   158  	buf := make([]byte, 8*len(k.S))
   159  	n := k.size
   160  	for {
   161  		for i := range k.S {
   162  			putUint64le(buf[i*8:], k.S[i])
   163  		}
   164  		if n <= k.blockSize {
   165  			b = append(b, buf[:n]...)
   166  			break
   167  		}
   168  		b = append(b, buf[:k.blockSize]...)
   169  		n -= k.blockSize
   170  		keccakf(&k.S)
   171  	}
   172  	return b
   173  }
   174  
   175  func keccakf(S *[25]uint64) {
   176  	var bc0, bc1, bc2, bc3, bc4 uint64
   177  	var S0, S1, S2, S3, S4 uint64
   178  	var S5, S6, S7, S8, S9 uint64
   179  	var S10, S11, S12, S13, S14 uint64
   180  	var S15, S16, S17, S18, S19 uint64
   181  	var S20, S21, S22, S23, S24 uint64
   182  	var tmp uint64
   183  
   184  	//S[0]=0x2073692073696854;
   185  	//S[1]=0x1747365742061
   186  	// S[16]=0x8000000000000000;
   187  
   188  	/* for i :=0; i< 25;i++{
   189  	    fmt.Printf("%2d %X\n", i, S[i])
   190  	   }
   191  	*/
   192  
   193  	S0, S1, S2, S3, S4 = S[0], S[1], S[2], S[3], S[4]
   194  	S5, S6, S7, S8, S9 = S[5], S[6], S[7], S[8], S[9]
   195  	S10, S11, S12, S13, S14 = S[10], S[11], S[12], S[13], S[14]
   196  	S15, S16, S17, S18, S19 = S[15], S[16], S[17], S[18], S[19]
   197  	S20, S21, S22, S23, S24 = S[20], S[21], S[22], S[23], S[24]
   198  
   199  	for r := 0; r < rounds; r++ {
   200  		// theta
   201  		bc0 = S0 ^ S5 ^ S10 ^ S15 ^ S20
   202  		bc1 = S1 ^ S6 ^ S11 ^ S16 ^ S21
   203  		bc2 = S2 ^ S7 ^ S12 ^ S17 ^ S22
   204  		bc3 = S3 ^ S8 ^ S13 ^ S18 ^ S23
   205  		bc4 = S4 ^ S9 ^ S14 ^ S19 ^ S24
   206  		tmp = bc4 ^ (bc1<<1 | bc1>>(64-1))
   207  		S0 ^= tmp
   208  		S5 ^= tmp
   209  		S10 ^= tmp
   210  		S15 ^= tmp
   211  		S20 ^= tmp
   212  		tmp = bc0 ^ (bc2<<1 | bc2>>(64-1))
   213  		S1 ^= tmp
   214  		S6 ^= tmp
   215  		S11 ^= tmp
   216  		S16 ^= tmp
   217  		S21 ^= tmp
   218  		tmp = bc1 ^ (bc3<<1 | bc3>>(64-1))
   219  		S2 ^= tmp
   220  		S7 ^= tmp
   221  		S12 ^= tmp
   222  		S17 ^= tmp
   223  		S22 ^= tmp
   224  		tmp = bc2 ^ (bc4<<1 | bc4>>(64-1))
   225  		S3 ^= tmp
   226  		S8 ^= tmp
   227  		S13 ^= tmp
   228  		S18 ^= tmp
   229  		S23 ^= tmp
   230  		tmp = bc3 ^ (bc0<<1 | bc0>>(64-1))
   231  		S4 ^= tmp
   232  		S9 ^= tmp
   233  		S14 ^= tmp
   234  		S19 ^= tmp
   235  		S24 ^= tmp
   236  
   237  		// rho phi
   238  		tmp = S1
   239  		tmp, S10 = S10, tmp<<1|tmp>>(64-1)
   240  		tmp, S7 = S7, tmp<<3|tmp>>(64-3)
   241  		tmp, S11 = S11, tmp<<6|tmp>>(64-6)
   242  		tmp, S17 = S17, tmp<<10|tmp>>(64-10)
   243  		tmp, S18 = S18, tmp<<15|tmp>>(64-15)
   244  		tmp, S3 = S3, tmp<<21|tmp>>(64-21)
   245  		tmp, S5 = S5, tmp<<28|tmp>>(64-28)
   246  		tmp, S16 = S16, tmp<<36|tmp>>(64-36)
   247  		tmp, S8 = S8, tmp<<45|tmp>>(64-45)
   248  		tmp, S21 = S21, tmp<<55|tmp>>(64-55)
   249  		tmp, S24 = S24, tmp<<2|tmp>>(64-2)
   250  		tmp, S4 = S4, tmp<<14|tmp>>(64-14)
   251  		tmp, S15 = S15, tmp<<27|tmp>>(64-27)
   252  		tmp, S23 = S23, tmp<<41|tmp>>(64-41)
   253  		tmp, S19 = S19, tmp<<56|tmp>>(64-56)
   254  		tmp, S13 = S13, tmp<<8|tmp>>(64-8)
   255  		tmp, S12 = S12, tmp<<25|tmp>>(64-25)
   256  		tmp, S2 = S2, tmp<<43|tmp>>(64-43)
   257  		tmp, S20 = S20, tmp<<62|tmp>>(64-62)
   258  		tmp, S14 = S14, tmp<<18|tmp>>(64-18)
   259  		tmp, S22 = S22, tmp<<39|tmp>>(64-39)
   260  		tmp, S9 = S9, tmp<<61|tmp>>(64-61)
   261  		tmp, S6 = S6, tmp<<20|tmp>>(64-20)
   262  		S1 = tmp<<44 | tmp>>(64-44)
   263  
   264  		// chi
   265  		bc0 = S0
   266  		bc1 = S1
   267  		bc2 = S2
   268  		bc3 = S3
   269  		bc4 = S4
   270  		S0 ^= (^bc1) & bc2
   271  		S1 ^= (^bc2) & bc3
   272  		S2 ^= (^bc3) & bc4
   273  		S3 ^= (^bc4) & bc0
   274  		S4 ^= (^bc0) & bc1
   275  		bc0 = S5
   276  		bc1 = S6
   277  		bc2 = S7
   278  		bc3 = S8
   279  		bc4 = S9
   280  		S5 ^= (^bc1) & bc2
   281  		S6 ^= (^bc2) & bc3
   282  		S7 ^= (^bc3) & bc4
   283  		S8 ^= (^bc4) & bc0
   284  		S9 ^= (^bc0) & bc1
   285  		bc0 = S10
   286  		bc1 = S11
   287  		bc2 = S12
   288  		bc3 = S13
   289  		bc4 = S14
   290  		S10 ^= (^bc1) & bc2
   291  		S11 ^= (^bc2) & bc3
   292  		S12 ^= (^bc3) & bc4
   293  		S13 ^= (^bc4) & bc0
   294  		S14 ^= (^bc0) & bc1
   295  		bc0 = S15
   296  		bc1 = S16
   297  		bc2 = S17
   298  		bc3 = S18
   299  		bc4 = S19
   300  		S15 ^= (^bc1) & bc2
   301  		S16 ^= (^bc2) & bc3
   302  		S17 ^= (^bc3) & bc4
   303  		S18 ^= (^bc4) & bc0
   304  		S19 ^= (^bc0) & bc1
   305  		bc0 = S20
   306  		bc1 = S21
   307  		bc2 = S22
   308  		bc3 = S23
   309  		bc4 = S24
   310  		S20 ^= (^bc1) & bc2
   311  		S21 ^= (^bc2) & bc3
   312  		S22 ^= (^bc3) & bc4
   313  		S23 ^= (^bc4) & bc0
   314  		S24 ^= (^bc0) & bc1
   315  
   316  		// iota
   317  		S0 ^= roundConstants[r]
   318  	}
   319  
   320  	S[0], S[1], S[2], S[3], S[4] = S0, S1, S2, S3, S4
   321  	S[5], S[6], S[7], S[8], S[9] = S5, S6, S7, S8, S9
   322  	S[10], S[11], S[12], S[13], S[14] = S10, S11, S12, S13, S14
   323  	S[15], S[16], S[17], S[18], S[19] = S15, S16, S17, S18, S19
   324  	S[20], S[21], S[22], S[23], S[24] = S20, S21, S22, S23, S24
   325  
   326  }
   327  
   328  func uint64le(v []byte) uint64 {
   329  	return uint64(v[0]) |
   330  		uint64(v[1])<<8 |
   331  		uint64(v[2])<<16 |
   332  		uint64(v[3])<<24 |
   333  		uint64(v[4])<<32 |
   334  		uint64(v[5])<<40 |
   335  		uint64(v[6])<<48 |
   336  		uint64(v[7])<<56
   337  
   338  }
   339  
   340  func putUint64le(v []byte, x uint64) {
   341  	v[0] = byte(x)
   342  	v[1] = byte(x >> 8)
   343  	v[2] = byte(x >> 16)
   344  	v[3] = byte(x >> 24)
   345  	v[4] = byte(x >> 32)
   346  	v[5] = byte(x >> 40)
   347  	v[6] = byte(x >> 48)
   348  	v[7] = byte(x >> 56)
   349  }