github.com/deso-protocol/core@v1.2.9/desohash/sha3m/sha3.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package sha3m
     6  
     7  // spongeDirection indicates the direction bytes are flowing through the sponge.
     8  type spongeDirection int
     9  
    10  const (
    11  	// spongeAbsorbing indicates that the sponge is absorbing input.
    12  	spongeAbsorbing spongeDirection = iota
    13  	// spongeSqueezing indicates that the sponge is being squeezed.
    14  	spongeSqueezing
    15  )
    16  
    17  const (
    18  	// maxRate is the maximum size of the internal buffer. SHAKE-256
    19  	// currently needs the largest buffer.
    20  	maxRate = 168
    21  )
    22  
    23  type state struct {
    24  	// Generic sponge components.
    25  	a    [25]uint64 // main state of the hash
    26  	buf  []byte     // points into storage
    27  	rate int        // the number of bytes of state to use
    28  
    29  	// dsbyte contains the "domain separation" bits and the first bit of
    30  	// the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
    31  	// SHA-3 and SHAKE functions by appending bitstrings to the message.
    32  	// Using a little-endian bit-ordering convention, these are "01" for SHA-3
    33  	// and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
    34  	// padding rule from section 5.1 is applied to pad the message to a multiple
    35  	// of the rate, which involves adding a "1" bit, zero or more "0" bits, and
    36  	// a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
    37  	// giving 00000110b (0x06) and 00011111b (0x1f).
    38  	// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
    39  	//     "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
    40  	//      Extendable-Output Functions (May 2014)"
    41  	dsbyte byte
    42  
    43  	storage storageBuf
    44  
    45  	// Specific to SHA-3 and SHAKE.
    46  	outputLen int             // the default output size in bytes
    47  	state     spongeDirection // whether the sponge is absorbing or squeezing
    48  }
    49  
    50  // BlockSize returns the rate of sponge underlying this hash function.
    51  func (d *state) BlockSize() int { return d.rate }
    52  
    53  // Size returns the output size of the hash function in bytes.
    54  func (d *state) Size() int { return d.outputLen }
    55  
    56  // Reset clears the internal state by zeroing the sponge state and
    57  // the byte buffer, and setting Sponge.state to absorbing.
    58  func (d *state) Reset() {
    59  	// Zero the permutation's state.
    60  	for i := range d.a {
    61  		d.a[i] = 0
    62  	}
    63  	d.state = spongeAbsorbing
    64  	d.buf = d.storage.asBytes()[:0]
    65  }
    66  
    67  func (d *state) clone() *state {
    68  	ret := *d
    69  	if ret.state == spongeAbsorbing {
    70  		ret.buf = ret.storage.asBytes()[:len(ret.buf)]
    71  	} else {
    72  		ret.buf = ret.storage.asBytes()[d.rate-cap(d.buf) : d.rate]
    73  	}
    74  
    75  	return &ret
    76  }
    77  
    78  // permute applies the KeccakF-1600 permutation. It handles
    79  // any input-output buffering.
    80  func (d *state) permute() {
    81  	switch d.state {
    82  	case spongeAbsorbing:
    83  		// If we're absorbing, we need to xor the input into the state
    84  		// before applying the permutation.
    85  		xorIn(d, d.buf)
    86  		d.buf = d.storage.asBytes()[:0]
    87  		keccakF1600(&d.a)
    88  	case spongeSqueezing:
    89  		// If we're squeezing, we need to apply the permutatin before
    90  		// copying more output.
    91  		keccakF1600(&d.a)
    92  		d.buf = d.storage.asBytes()[:d.rate]
    93  		copyOut(d, d.buf)
    94  	}
    95  }
    96  
    97  // pads appends the domain separation bits in dsbyte, applies
    98  // the multi-bitrate 10..1 padding rule, and permutes the state.
    99  func (d *state) padAndPermute(dsbyte byte) {
   100  	if d.buf == nil {
   101  		d.buf = d.storage.asBytes()[:0]
   102  	}
   103  	// Pad with this instance's domain-separator bits. We know that there's
   104  	// at least one byte of space in d.buf because, if it were full,
   105  	// permute would have been called to empty it. dsbyte also contains the
   106  	// first one bit for the padding. See the comment in the state struct.
   107  	d.buf = append(d.buf, dsbyte)
   108  	zerosStart := len(d.buf)
   109  	d.buf = d.storage.asBytes()[:d.rate]
   110  	for i := zerosStart; i < d.rate; i++ {
   111  		d.buf[i] = 0
   112  	}
   113  	// This adds the final one bit for the padding. Because of the way that
   114  	// bits are numbered from the LSB upwards, the final bit is the MSB of
   115  	// the last byte.
   116  	d.buf[d.rate-1] ^= 0x80
   117  	// Apply the permutation
   118  	d.permute()
   119  	d.state = spongeSqueezing
   120  	d.buf = d.storage.asBytes()[:d.rate]
   121  	copyOut(d, d.buf)
   122  }
   123  
   124  // Write absorbs more data into the hash's state. It produces an error
   125  // if more data is written to the ShakeHash after writing
   126  func (d *state) Write(p []byte) (written int, err error) {
   127  	if d.state != spongeAbsorbing {
   128  		panic("sha3: write to sponge after read")
   129  	}
   130  	if d.buf == nil {
   131  		d.buf = d.storage.asBytes()[:0]
   132  	}
   133  	written = len(p)
   134  
   135  	for len(p) > 0 {
   136  		if len(d.buf) == 0 && len(p) >= d.rate {
   137  			// The fast path; absorb a full "rate" bytes of input and apply the permutation.
   138  			xorIn(d, p[:d.rate])
   139  			p = p[d.rate:]
   140  			keccakF1600(&d.a)
   141  		} else {
   142  			// The slow path; buffer the input until we can fill the sponge, and then xor it in.
   143  			todo := d.rate - len(d.buf)
   144  			if todo > len(p) {
   145  				todo = len(p)
   146  			}
   147  			d.buf = append(d.buf, p[:todo]...)
   148  			p = p[todo:]
   149  
   150  			// If the sponge is full, apply the permutation.
   151  			if len(d.buf) == d.rate {
   152  				d.permute()
   153  			}
   154  		}
   155  	}
   156  
   157  	return
   158  }
   159  
   160  // Read squeezes an arbitrary number of bytes from the sponge.
   161  func (d *state) Read(out []byte) (n int, err error) {
   162  	// If we're still absorbing, pad and apply the permutation.
   163  	if d.state == spongeAbsorbing {
   164  		d.padAndPermute(d.dsbyte)
   165  	}
   166  
   167  	n = len(out)
   168  
   169  	// Now, do the squeezing.
   170  	for len(out) > 0 {
   171  		n := copy(out, d.buf)
   172  		d.buf = d.buf[n:]
   173  		out = out[n:]
   174  
   175  		// Apply the permutation if we've squeezed the sponge dry.
   176  		if len(d.buf) == 0 {
   177  			d.permute()
   178  		}
   179  	}
   180  
   181  	return
   182  }
   183  
   184  // Sum applies padding to the hash state and then squeezes out the desired
   185  // number of output bytes.
   186  func (d *state) Sum(in []byte) []byte {
   187  	// Make a copy of the original hash so that caller can keep writing
   188  	// and summing.
   189  	dup := d.clone()
   190  	hash := make([]byte, dup.outputLen)
   191  	dup.Read(hash)
   192  	return append(in, hash...)
   193  }