// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sha3 implements the SHA-3 fixed-output-length hash functions and // the SHAKE variable-output-length functions defined by [FIPS 202], as well as // the cSHAKE extendable-output-length functions defined by [SP 800-185]. // // [FIPS 202]: https://doi.org/10.6028/NIST.FIPS.202 // [SP 800-185]: https://doi.org/10.6028/NIST.SP.800-185
package sha3 import ( ) // spongeDirection indicates the direction bytes are flowing through the sponge. type spongeDirection int const ( // spongeAbsorbing indicates that the sponge is absorbing input. spongeAbsorbing spongeDirection = iota // spongeSqueezing indicates that the sponge is being squeezed. spongeSqueezing ) type Digest struct { a [1600 / 8]byte // main state of the hash // a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR // into before running the permutation. If squeezing, it's the remaining // output to produce before running the permutation. n, rate int // dsbyte contains the "domain separation" bits and the first bit of // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the // SHA-3 and SHAKE functions by appending bitstrings to the message. // Using a little-endian bit-ordering convention, these are "01" for SHA-3 // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the // padding rule from section 5.1 is applied to pad the message to a multiple // of the rate, which involves adding a "1" bit, zero or more "0" bits, and // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, // giving 00000110b (0x06) and 00011111b (0x1f). // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and // Extendable-Output Functions (May 2014)" dsbyte byte outputLen int // the default output size in bytes state spongeDirection // whether the sponge is absorbing or squeezing } // BlockSize returns the rate of sponge underlying this hash function. func ( *Digest) () int { return .rate } // Size returns the output size of the hash function in bytes. func ( *Digest) () int { return .outputLen } // Reset resets the Digest to its initial state. func ( *Digest) () { // Zero the permutation's state. for := range .a { .a[] = 0 } .state = spongeAbsorbing .n = 0 } func ( *Digest) () *Digest { := * return & } // permute applies the KeccakF-1600 permutation. func ( *Digest) () { keccakF1600(&.a) .n = 0 } // padAndPermute appends the domain separation bits in dsbyte, applies // the multi-bitrate 10..1 padding rule, and permutes the state. func ( *Digest) () { // Pad with this instance's domain-separator bits. We know that there's // at least one byte of space in the sponge because, if it were full, // permute would have been called to empty it. dsbyte also contains the // first one bit for the padding. See the comment in the state struct. .a[.n] ^= .dsbyte // This adds the final one bit for the padding. Because of the way that // bits are numbered from the LSB upwards, the final bit is the MSB of // the last byte. .a[.rate-1] ^= 0x80 // Apply the permutation .permute() .state = spongeSqueezing } // Write absorbs more data into the hash's state. func ( *Digest) ( []byte) ( int, error) { return .write() } func ( *Digest) ( []byte) ( int, error) { if .state != spongeAbsorbing { panic("sha3: Write after Read") } = len() for len() > 0 { := subtle.XORBytes(.a[.n:.rate], .a[.n:.rate], ) .n += = [:] // If the sponge is full, apply the permutation. if .n == .rate { .permute() } } return } // read squeezes an arbitrary number of bytes from the sponge. func ( *Digest) ( []byte) ( int, error) { // If we're still absorbing, pad and apply the permutation. if .state == spongeAbsorbing { .padAndPermute() } = len() // Now, do the squeezing. for len() > 0 { // Apply the permutation if we've squeezed the sponge dry. if .n == .rate { .permute() } := copy(, .a[.n:.rate]) .n += = [:] } return } // Sum appends the current hash to b and returns the resulting slice. // It does not change the underlying hash state. func ( *Digest) ( []byte) []byte { fips140.RecordApproved() return .sum() } func ( *Digest) ( []byte) []byte { if .state != spongeAbsorbing { panic("sha3: Sum after Read") } // Make a copy of the original hash so that caller can keep writing // and summing. := .Clone() := make([]byte, .outputLen, 64) // explicit cap to allow stack allocation .read() return append(, ...) } const ( magicSHA3 = "sha\x08" magicShake = "sha\x09" magicCShake = "sha\x0a" magicKeccak = "sha\x0b" // magic || rate || main state || n || sponge direction marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1 ) func ( *Digest) () ([]byte, error) { return .AppendBinary(make([]byte, 0, marshaledSize)) } func ( *Digest) ( []byte) ([]byte, error) { switch .dsbyte { case dsbyteSHA3: = append(, magicSHA3...) case dsbyteShake: = append(, magicShake...) case dsbyteCShake: = append(, magicCShake...) case dsbyteKeccak: = append(, magicKeccak...) default: panic("unknown dsbyte") } // rate is at most 168, and n is at most rate. = append(, byte(.rate)) = append(, .a[:]...) = append(, byte(.n), byte(.state)) return , nil } func ( *Digest) ( []byte) error { if len() != marshaledSize { return errors.New("sha3: invalid hash state") } := string([:len(magicSHA3)]) = [len(magicSHA3):] switch { case == magicSHA3 && .dsbyte == dsbyteSHA3: case == magicShake && .dsbyte == dsbyteShake: case == magicCShake && .dsbyte == dsbyteCShake: case == magicKeccak && .dsbyte == dsbyteKeccak: default: return errors.New("sha3: invalid hash state identifier") } := int([0]) = [1:] if != .rate { return errors.New("sha3: invalid hash state function") } copy(.a[:], ) = [len(.a):] , := int([0]), spongeDirection([1]) if > .rate { return errors.New("sha3: invalid hash state") } .n = if != spongeAbsorbing && != spongeSqueezing { return errors.New("sha3: invalid hash state") } .state = return nil }