// 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// This file defines the ShakeHash interface, and provides// functions for creating SHAKE and cSHAKE instances, as well as utility// functions for hashing bytes to arbitrary-length output.////// SHAKE implementation is based on FIPS PUB 202 [1]// cSHAKE implementations is based on NIST SP 800-185 [2]//// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf// [2] https://doi.org/10.6028/NIST.SP.800-185import ()// ShakeHash defines the interface to hash functions that support// arbitrary-length output. When used as a plain [hash.Hash], it// produces minimum-length outputs that provide full-strength generic// security.typeShakeHashinterface {hash.Hash// Read reads more output from the hash; reading affects the hash's // state. (ShakeHash.Read is thus very different from Hash.Sum) // It never returns an error, but subsequent calls to Write or Sum // will panic.io.Reader// Clone returns a copy of the ShakeHash in its current state.Clone() ShakeHash}// cSHAKE specific contexttype cshakeState struct { *state// SHA-3 state context and Read/Write operations// initBlock is the cSHAKE specific initialization set of bytes. It is initialized // by newCShake function and stores concatenation of N followed by S, encoded // by the method specified in 3.3 of [1]. // It is stored here in order for Reset() to be able to put context into // initial state. initBlock []byte}func bytepad( []byte, int) []byte { := make([]byte, 0, 9+len()+-1) = append(, leftEncode(uint64())...) = append(, ...)if := - len()%; < { = append(, make([]byte, )...) }return}func leftEncode( uint64) []byte {// Let n be the smallest positive integer for which 2^(8n) > x. := (bits.Len64() + 7) / 8if == 0 { = 1 }// Return n || x with n as a byte and x an n bytes in big-endian order. := make([]byte, 9)binary.BigEndian.PutUint64([1:], ) = [9--1:] [0] = byte()return}func newCShake(, []byte, , int, byte) ShakeHash { := cshakeState{state: &state{rate: , outputLen: , dsbyte: }} .initBlock = make([]byte, 0, 9+len()+9+len()) // leftEncode returns max 9 bytes .initBlock = append(.initBlock, leftEncode(uint64(len())*8)...) .initBlock = append(.initBlock, ...) .initBlock = append(.initBlock, leftEncode(uint64(len())*8)...) .initBlock = append(.initBlock, ...) .Write(bytepad(.initBlock, .rate))return &}// Reset resets the hash to initial state.func ( *cshakeState) () { .state.Reset() .Write(bytepad(.initBlock, .rate))}// Clone returns copy of a cSHAKE context within its current state.func ( *cshakeState) () ShakeHash { := make([]byte, len(.initBlock))copy(, .initBlock)return &cshakeState{state: .clone(), initBlock: }}// Clone returns copy of SHAKE context within its current state.func ( *state) () ShakeHash {return .clone()}func ( *cshakeState) () ([]byte, error) {return .AppendBinary(make([]byte, 0, marshaledSize+len(.initBlock)))}func ( *cshakeState) ( []byte) ([]byte, error) { , := .state.AppendBinary()if != nil {returnnil, } = append(, .initBlock...)return , nil}func ( *cshakeState) ( []byte) error {iflen() <= marshaledSize {returnerrors.New("sha3: invalid hash state") }if := .state.UnmarshalBinary([:marshaledSize]); != nil {return } .initBlock = bytes.Clone([marshaledSize:])returnnil}// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash.// Its generic security strength is 128 bits against all attacks if at// least 32 bytes of its output are used.func () ShakeHash {returnnewShake128()}// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash.// Its generic security strength is 256 bits against all attacks if// at least 64 bytes of its output are used.func () ShakeHash {returnnewShake256()}func newShake128Generic() *state {return &state{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}}func newShake256Generic() *state {return &state{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}}// NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash,// a customizable variant of SHAKE128.// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is// desired. S is a customization byte string used for domain separation - two cSHAKE// computations on same input with different S yield unrelated outputs.// When N and S are both empty, this is equivalent to NewShake128.func (, []byte) ShakeHash {iflen() == 0 && len() == 0 {returnNewShake128() }returnnewCShake(, , rateK256, 32, dsbyteCShake)}// NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash,// a customizable variant of SHAKE256.// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is// desired. S is a customization byte string used for domain separation - two cSHAKE// computations on same input with different S yield unrelated outputs.// When N and S are both empty, this is equivalent to NewShake256.func (, []byte) ShakeHash {iflen() == 0 && len() == 0 {returnNewShake256() }returnnewCShake(, , rateK512, 64, dsbyteCShake)}// ShakeSum128 writes an arbitrary-length digest of data into hash.func (, []byte) { := NewShake128() .Write() .Read()}// ShakeSum256 writes an arbitrary-length digest of data into hash.func (, []byte) { := NewShake256() .Write() .Read()}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.