shake.go raw

   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  // This file defines the ShakeHash interface, and provides
   8  // functions for creating SHAKE and cSHAKE instances, as well as utility
   9  // functions for hashing bytes to arbitrary-length output.
  10  //
  11  //
  12  // SHAKE implementation is based on FIPS PUB 202 [1]
  13  // cSHAKE implementations is based on NIST SP 800-185 [2]
  14  //
  15  // [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
  16  // [2] https://doi.org/10.6028/NIST.SP.800-185
  17  
  18  import (
  19  	"io"
  20  )
  21  
  22  // ShakeHash defines the interface to hash functions that
  23  // support arbitrary-length output.
  24  type ShakeHash interface {
  25  	// Write absorbs more data into the hash's state. It panics if input is
  26  	// written to it after output has been read from it.
  27  	io.Writer
  28  
  29  	// Read reads more output from the hash; reading affects the hash's
  30  	// state. (ShakeHash.Read is thus very different from Hash.Sum)
  31  	// It never returns an error.
  32  	io.Reader
  33  
  34  	// Clone returns a copy of the ShakeHash in its current state.
  35  	Clone() ShakeHash
  36  
  37  	// Reset resets the ShakeHash to its initial state.
  38  	Reset()
  39  }
  40  
  41  // Consts for configuring initial SHA-3 state
  42  const (
  43  	dsbyteShake = 0x1f
  44  	rate128     = 168
  45  	rate256     = 136
  46  )
  47  
  48  // Clone returns copy of SHAKE context within its current state.
  49  func (d *State) Clone() ShakeHash {
  50  	return d.clone()
  51  }
  52  
  53  // NewShake128 creates a new SHAKE128 variable-output-length ShakeHash.
  54  // Its generic security strength is 128 bits against all attacks if at
  55  // least 32 bytes of its output are used.
  56  func NewShake128() State {
  57  	return State{rate: rate128, dsbyte: dsbyteShake}
  58  }
  59  
  60  // NewTurboShake128 creates a new TurboSHAKE128 variable-output-length ShakeHash.
  61  // Its generic security strength is 128 bits against all attacks if at
  62  // least 32 bytes of its output are used.
  63  // D is the domain separation byte and must be between 0x01 and 0x7f inclusive.
  64  func NewTurboShake128(D byte) State {
  65  	if D == 0 || D > 0x7f {
  66  		panic("turboshake: D out of range")
  67  	}
  68  	return State{rate: rate128, dsbyte: D, turbo: true}
  69  }
  70  
  71  // NewShake256 creates a new SHAKE256 variable-output-length ShakeHash.
  72  // Its generic security strength is 256 bits against all attacks if
  73  // at least 64 bytes of its output are used.
  74  func NewShake256() State {
  75  	return State{rate: rate256, dsbyte: dsbyteShake}
  76  }
  77  
  78  // NewTurboShake256 creates a new TurboSHAKE256 variable-output-length ShakeHash.
  79  // Its generic security strength is 256 bits against all attacks if
  80  // at least 64 bytes of its output are used.
  81  // D is the domain separation byte and must be between 0x01 and 0x7f inclusive.
  82  func NewTurboShake256(D byte) State {
  83  	if D == 0 || D > 0x7f {
  84  		panic("turboshake: D out of range")
  85  	}
  86  	return State{rate: rate256, dsbyte: D, turbo: true}
  87  }
  88  
  89  // ShakeSum128 writes an arbitrary-length digest of data into hash.
  90  func ShakeSum128(hash, data []byte) {
  91  	h := NewShake128()
  92  	_, _ = h.Write(data)
  93  	_, _ = h.Read(hash)
  94  }
  95  
  96  // ShakeSum256 writes an arbitrary-length digest of data into hash.
  97  func ShakeSum256(hash, data []byte) {
  98  	h := NewShake256()
  99  	_, _ = h.Write(data)
 100  	_, _ = h.Read(hash)
 101  }
 102  
 103  // TurboShakeSum128 writes an arbitrary-length digest of data into hash.
 104  func TurboShakeSum128(hash, data []byte, D byte) {
 105  	h := NewTurboShake128(D)
 106  	_, _ = h.Write(data)
 107  	_, _ = h.Read(hash)
 108  }
 109  
 110  // TurboShakeSum256 writes an arbitrary-length digest of data into hash.
 111  func TurboShakeSum256(hash, data []byte, D byte) {
 112  	h := NewTurboShake256(D)
 113  	_, _ = h.Write(data)
 114  	_, _ = h.Read(hash)
 115  }
 116  
 117  func (d *State) SwitchDS(D byte) {
 118  	d.dsbyte = D
 119  }
 120