github.com/chain5j/chain5j-pkg@v1.0.7/crypto/hashalg/sha3/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 sha3
     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  	storage [maxRate]byte
    43  
    44  	// Specific to SHA-3 and SHAKE.
    45  	outputLen int             // the default output size in bytes
    46  	state     spongeDirection // whether the sponge is absorbing or squeezing
    47  }
    48  
    49  // BlockSize returns the rate of sponge underlying this hash function.
    50  func (d *state) BlockSize() int { return d.rate }
    51  
    52  // Size returns the output size of the hash function in bytes.
    53  func (d *state) Size() int { return d.outputLen }
    54  
    55  // Reset clears the internal state by zeroing the sponge state and
    56  // the byte buffer, and setting Sponge.state to absorbing.
    57  func (d *state) Reset() {
    58  	// Zero the permutation's state.
    59  	for i := range d.a {
    60  		d.a[i] = 0
    61  	}
    62  	d.state = spongeAbsorbing
    63  	d.buf = d.storage[:0]
    64  }
    65  
    66  func (d *state) clone() *state {
    67  	ret := *d
    68  	if ret.state == spongeAbsorbing {
    69  		ret.buf = ret.storage[:len(ret.buf)]
    70  	} else {
    71  		ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate]
    72  	}
    73  
    74  	return &ret
    75  }
    76  
    77  // permute applies the KeccakF-1600 permutation. It handles
    78  // any input-output buffering.
    79  func (d *state) permute() {
    80  	switch d.state {
    81  	case spongeAbsorbing:
    82  		// If we're absorbing, we need to xor the input into the state
    83  		// before applying the permutation.
    84  		xorIn(d, d.buf)
    85  		d.buf = d.storage[:0]
    86  		keccakF1600(&d.a)
    87  	case spongeSqueezing:
    88  		// If we're squeezing, we need to apply the permutatin before
    89  		// copying more output.
    90  		keccakF1600(&d.a)
    91  		d.buf = d.storage[:d.rate]
    92  		copyOut(d, d.buf)
    93  	}
    94  }
    95  
    96  // pads appends the domain separation bits in dsbyte, applies
    97  // the multi-bitrate 10..1 padding rule, and permutes the state.
    98  func (d *state) padAndPermute(dsbyte byte) {
    99  	if d.buf == nil {
   100  		d.buf = d.storage[:0]
   101  	}
   102  	// Pad with this instance's domain-separator bits. We know that there's
   103  	// at least one byte of space in d.buf because, if it were full,
   104  	// permute would have been called to empty it. dsbyte also contains the
   105  	// first one bit for the padding. See the comment in the state struct.
   106  	d.buf = append(d.buf, dsbyte)
   107  	zerosStart := len(d.buf)
   108  	d.buf = d.storage[:d.rate]
   109  	for i := zerosStart; i < d.rate; i++ {
   110  		d.buf[i] = 0
   111  	}
   112  	// This adds the final one bit for the padding. Because of the way that
   113  	// bits are numbered from the LSB upwards, the final bit is the MSB of
   114  	// the last byte.
   115  	d.buf[d.rate-1] ^= 0x80
   116  	// Apply the permutation
   117  	d.permute()
   118  	d.state = spongeSqueezing
   119  	d.buf = d.storage[:d.rate]
   120  	copyOut(d, d.buf)
   121  }
   122  
   123  // Write absorbs more data into the hash's state. It produces an error
   124  // if more data is written to the ShakeHash after writing
   125  func (d *state) Write(p []byte) (written int, err error) {
   126  	if d.state != spongeAbsorbing {
   127  		panic("sha3: write to sponge after read")
   128  	}
   129  	if d.buf == nil {
   130  		d.buf = d.storage[:0]
   131  	}
   132  	written = len(p)
   133  
   134  	for len(p) > 0 {
   135  		if len(d.buf) == 0 && len(p) >= d.rate {
   136  			// The fast path; absorb a full "rate" bytes of input and apply the permutation.
   137  			xorIn(d, p[:d.rate])
   138  			p = p[d.rate:]
   139  			keccakF1600(&d.a)
   140  		} else {
   141  			// The slow path; buffer the input until we can fill the sponge, and then xor it in.
   142  			todo := d.rate - len(d.buf)
   143  			if todo > len(p) {
   144  				todo = len(p)
   145  			}
   146  			d.buf = append(d.buf, p[:todo]...)
   147  			p = p[todo:]
   148  
   149  			// If the sponge is full, apply the permutation.
   150  			if len(d.buf) == d.rate {
   151  				d.permute()
   152  			}
   153  		}
   154  	}
   155  
   156  	return
   157  }
   158  
   159  // Read squeezes an arbitrary number of bytes from the sponge.
   160  func (d *state) Read(out []byte) (n int, err error) {
   161  	// If we're still absorbing, pad and apply the permutation.
   162  	if d.state == spongeAbsorbing {
   163  		d.padAndPermute(d.dsbyte)
   164  	}
   165  
   166  	n = len(out)
   167  
   168  	// Now, do the squeezing.
   169  	for len(out) > 0 {
   170  		n := copy(out, d.buf)
   171  		d.buf = d.buf[n:]
   172  		out = out[n:]
   173  
   174  		// Apply the permutation if we've squeezed the sponge dry.
   175  		if len(d.buf) == 0 {
   176  			d.permute()
   177  		}
   178  	}
   179  
   180  	return
   181  }
   182  
   183  // Sum applies padding to the hash state and then squeezes out the desired
   184  // number of output bytes.
   185  func (d *state) Sum(in []byte) []byte {
   186  	// Make a copy of the original hash so that caller can keep writing
   187  	// and summing.
   188  	dup := d.clone()
   189  	hash := make([]byte, dup.outputLen)
   190  	dup.Read(hash)
   191  	return append(in, hash...)
   192  }