Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/crypto/internal/fips140/sha3/sha3.go

     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 implements the SHA-3 fixed-output-length hash functions and
     6  // the SHAKE variable-output-length functions defined by [FIPS 202], as well as
     7  // the cSHAKE extendable-output-length functions defined by [SP 800-185].
     8  //
     9  // [FIPS 202]: https://doi.org/10.6028/NIST.FIPS.202
    10  // [SP 800-185]: https://doi.org/10.6028/NIST.SP.800-185
    11  package sha3
    12  
    13  import (
    14  	"crypto/internal/fips140"
    15  	"crypto/internal/fips140/subtle"
    16  	"errors"
    17  )
    18  
    19  // spongeDirection indicates the direction bytes are flowing through the sponge.
    20  type spongeDirection int
    21  
    22  const (
    23  	// spongeAbsorbing indicates that the sponge is absorbing input.
    24  	spongeAbsorbing spongeDirection = iota
    25  	// spongeSqueezing indicates that the sponge is being squeezed.
    26  	spongeSqueezing
    27  )
    28  
    29  type Digest struct {
    30  	a [1600 / 8]byte // main state of the hash
    31  
    32  	// a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR
    33  	// into before running the permutation. If squeezing, it's the remaining
    34  	// output to produce before running the permutation.
    35  	n, rate int
    36  
    37  	// dsbyte contains the "domain separation" bits and the first bit of
    38  	// the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
    39  	// SHA-3 and SHAKE functions by appending bitstrings to the message.
    40  	// Using a little-endian bit-ordering convention, these are "01" for SHA-3
    41  	// and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
    42  	// padding rule from section 5.1 is applied to pad the message to a multiple
    43  	// of the rate, which involves adding a "1" bit, zero or more "0" bits, and
    44  	// a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
    45  	// giving 00000110b (0x06) and 00011111b (0x1f).
    46  	// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
    47  	//     "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
    48  	//      Extendable-Output Functions (May 2014)"
    49  	dsbyte byte
    50  
    51  	outputLen int             // the default output size in bytes
    52  	state     spongeDirection // whether the sponge is absorbing or squeezing
    53  }
    54  
    55  // BlockSize returns the rate of sponge underlying this hash function.
    56  func (d *Digest) BlockSize() int { return d.rate }
    57  
    58  // Size returns the output size of the hash function in bytes.
    59  func (d *Digest) Size() int { return d.outputLen }
    60  
    61  // Reset resets the Digest to its initial state.
    62  func (d *Digest) Reset() {
    63  	// Zero the permutation's state.
    64  	clear(d.a[:])
    65  	d.state = spongeAbsorbing
    66  	d.n = 0
    67  }
    68  
    69  func (d *Digest) Clone() *Digest {
    70  	ret := *d
    71  	return &ret
    72  }
    73  
    74  // permute applies the KeccakF-1600 permutation.
    75  func (d *Digest) permute() {
    76  	keccakF1600(&d.a)
    77  	d.n = 0
    78  }
    79  
    80  // padAndPermute appends the domain separation bits in dsbyte, applies
    81  // the multi-bitrate 10..1 padding rule, and permutes the state.
    82  func (d *Digest) padAndPermute() {
    83  	// Pad with this instance's domain-separator bits. We know that there's
    84  	// at least one byte of space in the sponge because, if it were full,
    85  	// permute would have been called to empty it. dsbyte also contains the
    86  	// first one bit for the padding. See the comment in the state struct.
    87  	d.a[d.n] ^= d.dsbyte
    88  	// This adds the final one bit for the padding. Because of the way that
    89  	// bits are numbered from the LSB upwards, the final bit is the MSB of
    90  	// the last byte.
    91  	d.a[d.rate-1] ^= 0x80
    92  	// Apply the permutation
    93  	d.permute()
    94  	d.state = spongeSqueezing
    95  }
    96  
    97  // Write absorbs more data into the hash's state.
    98  func (d *Digest) Write(p []byte) (n int, err error) { return d.write(p) }
    99  func (d *Digest) writeGeneric(p []byte) (n int, err error) {
   100  	if d.state != spongeAbsorbing {
   101  		panic("sha3: Write after Read")
   102  	}
   103  
   104  	n = len(p)
   105  
   106  	for len(p) > 0 {
   107  		x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
   108  		d.n += x
   109  		p = p[x:]
   110  
   111  		// If the sponge is full, apply the permutation.
   112  		if d.n == d.rate {
   113  			d.permute()
   114  		}
   115  	}
   116  
   117  	return
   118  }
   119  
   120  // read squeezes an arbitrary number of bytes from the sponge.
   121  func (d *Digest) readGeneric(out []byte) (n int, err error) {
   122  	// If we're still absorbing, pad and apply the permutation.
   123  	if d.state == spongeAbsorbing {
   124  		d.padAndPermute()
   125  	}
   126  
   127  	n = len(out)
   128  
   129  	// Now, do the squeezing.
   130  	for len(out) > 0 {
   131  		// Apply the permutation if we've squeezed the sponge dry.
   132  		if d.n == d.rate {
   133  			d.permute()
   134  		}
   135  
   136  		x := copy(out, d.a[d.n:d.rate])
   137  		d.n += x
   138  		out = out[x:]
   139  	}
   140  
   141  	return
   142  }
   143  
   144  // Sum appends the current hash to b and returns the resulting slice.
   145  // It does not change the underlying hash state.
   146  func (d *Digest) Sum(b []byte) []byte {
   147  	if d.dsbyte == dsbyteKeccak {
   148  		fips140.RecordNonApproved()
   149  	} else {
   150  		fips140.RecordApproved()
   151  	}
   152  	return d.sum(b)
   153  }
   154  
   155  func (d *Digest) sumGeneric(b []byte) []byte {
   156  	if d.state != spongeAbsorbing {
   157  		panic("sha3: Sum after Read")
   158  	}
   159  
   160  	// Make a copy of the original hash so that caller can keep writing
   161  	// and summing.
   162  	dup := d.Clone()
   163  	hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation
   164  	dup.read(hash)
   165  	return append(b, hash...)
   166  }
   167  
   168  const (
   169  	magicSHA3   = "sha\x08"
   170  	magicShake  = "sha\x09"
   171  	magicCShake = "sha\x0a"
   172  	magicKeccak = "sha\x0b"
   173  	// magic || rate || main state || n || sponge direction
   174  	marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
   175  )
   176  
   177  func (d *Digest) MarshalBinary() ([]byte, error) {
   178  	return d.AppendBinary(make([]byte, 0, marshaledSize))
   179  }
   180  
   181  func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
   182  	switch d.dsbyte {
   183  	case dsbyteSHA3:
   184  		b = append(b, magicSHA3...)
   185  	case dsbyteShake:
   186  		b = append(b, magicShake...)
   187  	case dsbyteCShake:
   188  		b = append(b, magicCShake...)
   189  	case dsbyteKeccak:
   190  		b = append(b, magicKeccak...)
   191  	default:
   192  		panic("unknown dsbyte")
   193  	}
   194  	// rate is at most 168, and n is at most rate.
   195  	b = append(b, byte(d.rate))
   196  	b = append(b, d.a[:]...)
   197  	b = append(b, byte(d.n), byte(d.state))
   198  	return b, nil
   199  }
   200  
   201  func (d *Digest) UnmarshalBinary(b []byte) error {
   202  	if len(b) != marshaledSize {
   203  		return errors.New("sha3: invalid hash state")
   204  	}
   205  
   206  	magic := string(b[:len(magicSHA3)])
   207  	b = b[len(magicSHA3):]
   208  	switch {
   209  	case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
   210  	case magic == magicShake && d.dsbyte == dsbyteShake:
   211  	case magic == magicCShake && d.dsbyte == dsbyteCShake:
   212  	case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
   213  	default:
   214  		return errors.New("sha3: invalid hash state identifier")
   215  	}
   216  
   217  	rate := int(b[0])
   218  	b = b[1:]
   219  	if rate != d.rate {
   220  		return errors.New("sha3: invalid hash state function")
   221  	}
   222  
   223  	copy(d.a[:], b)
   224  	b = b[len(d.a):]
   225  
   226  	n, state := int(b[0]), spongeDirection(b[1])
   227  	if n > d.rate {
   228  		return errors.New("sha3: invalid hash state")
   229  	}
   230  	d.n = n
   231  	if state != spongeAbsorbing && state != spongeSqueezing {
   232  		return errors.New("sha3: invalid hash state")
   233  	}
   234  	d.state = state
   235  
   236  	return nil
   237  }
   238  

View as plain text