sha3.mx raw

   1  // Copyright 2024 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 hash algorithms and the SHAKE extendable
   6  // output functions defined in FIPS 202.
   7  package sha3
   8  
   9  import (
  10  	"crypto"
  11  	"crypto/internal/fips140/sha3"
  12  	"hash"
  13  	_ "unsafe"
  14  )
  15  
  16  func init() {
  17  	crypto.RegisterHash(crypto.SHA3_224, func() hash.Hash { return New224() })
  18  	crypto.RegisterHash(crypto.SHA3_256, func() hash.Hash { return New256() })
  19  	crypto.RegisterHash(crypto.SHA3_384, func() hash.Hash { return New384() })
  20  	crypto.RegisterHash(crypto.SHA3_512, func() hash.Hash { return New512() })
  21  }
  22  
  23  // Sum224 returns the SHA3-224 hash of data.
  24  func Sum224(data []byte) [28]byte {
  25  	var out [28]byte
  26  	h := sha3.New224()
  27  	h.Write(data)
  28  	h.Sum(out[:0])
  29  	return out
  30  }
  31  
  32  // Sum256 returns the SHA3-256 hash of data.
  33  func Sum256(data []byte) [32]byte {
  34  	var out [32]byte
  35  	h := sha3.New256()
  36  	h.Write(data)
  37  	h.Sum(out[:0])
  38  	return out
  39  }
  40  
  41  // Sum384 returns the SHA3-384 hash of data.
  42  func Sum384(data []byte) [48]byte {
  43  	var out [48]byte
  44  	h := sha3.New384()
  45  	h.Write(data)
  46  	h.Sum(out[:0])
  47  	return out
  48  }
  49  
  50  // Sum512 returns the SHA3-512 hash of data.
  51  func Sum512(data []byte) [64]byte {
  52  	var out [64]byte
  53  	h := sha3.New512()
  54  	h.Write(data)
  55  	h.Sum(out[:0])
  56  	return out
  57  }
  58  
  59  // SumSHAKE128 applies the SHAKE128 extendable output function to data and
  60  // returns an output of the given length in bytes.
  61  func SumSHAKE128(data []byte, length int) []byte {
  62  	// Outline the allocation for up to 256 bits of output to the caller's stack.
  63  	out := []byte{:32}
  64  	return sumSHAKE128(out, data, length)
  65  }
  66  
  67  func sumSHAKE128(out, data []byte, length int) []byte {
  68  	if len(out) < length {
  69  		out = []byte{:length}
  70  	} else {
  71  		out = out[:length]
  72  	}
  73  	h := sha3.NewShake128()
  74  	h.Write(data)
  75  	h.Read(out)
  76  	return out
  77  }
  78  
  79  // SumSHAKE256 applies the SHAKE256 extendable output function to data and
  80  // returns an output of the given length in bytes.
  81  func SumSHAKE256(data []byte, length int) []byte {
  82  	// Outline the allocation for up to 512 bits of output to the caller's stack.
  83  	out := []byte{:64}
  84  	return sumSHAKE256(out, data, length)
  85  }
  86  
  87  func sumSHAKE256(out, data []byte, length int) []byte {
  88  	if len(out) < length {
  89  		out = []byte{:length}
  90  	} else {
  91  		out = out[:length]
  92  	}
  93  	h := sha3.NewShake256()
  94  	h.Write(data)
  95  	h.Read(out)
  96  	return out
  97  }
  98  
  99  // SHA3 is an instance of a SHA-3 hash. It implements [hash.Hash].
 100  type SHA3 struct {
 101  	s sha3.Digest
 102  }
 103  
 104  //go:linkname fips140hash_sha3Unwrap crypto/internal/fips140hash.sha3Unwrap
 105  func fips140hash_sha3Unwrap(sha3 *SHA3) *sha3.Digest {
 106  	return &sha3.s
 107  }
 108  
 109  // New224 creates a new SHA3-224 hash.
 110  func New224() *SHA3 {
 111  	return &SHA3{*sha3.New224()}
 112  }
 113  
 114  // New256 creates a new SHA3-256 hash.
 115  func New256() *SHA3 {
 116  	return &SHA3{*sha3.New256()}
 117  }
 118  
 119  // New384 creates a new SHA3-384 hash.
 120  func New384() *SHA3 {
 121  	return &SHA3{*sha3.New384()}
 122  }
 123  
 124  // New512 creates a new SHA3-512 hash.
 125  func New512() *SHA3 {
 126  	return &SHA3{*sha3.New512()}
 127  }
 128  
 129  // Write absorbs more data into the hash's state.
 130  func (s *SHA3) Write(p []byte) (n int, err error) {
 131  	return s.s.Write(p)
 132  }
 133  
 134  // Sum appends the current hash to b and returns the resulting slice.
 135  func (s *SHA3) Sum(b []byte) []byte {
 136  	return s.s.Sum(b)
 137  }
 138  
 139  // Reset resets the hash to its initial state.
 140  func (s *SHA3) Reset() {
 141  	s.s.Reset()
 142  }
 143  
 144  // Size returns the number of bytes Sum will produce.
 145  func (s *SHA3) Size() int {
 146  	return s.s.Size()
 147  }
 148  
 149  // BlockSize returns the hash's rate.
 150  func (s *SHA3) BlockSize() int {
 151  	return s.s.BlockSize()
 152  }
 153  
 154  // MarshalBinary implements [encoding.BinaryMarshaler].
 155  func (s *SHA3) MarshalBinary() ([]byte, error) {
 156  	return s.s.MarshalBinary()
 157  }
 158  
 159  // AppendBinary implements [encoding.BinaryAppender].
 160  func (s *SHA3) AppendBinary(p []byte) ([]byte, error) {
 161  	return s.s.AppendBinary(p)
 162  }
 163  
 164  // UnmarshalBinary implements [encoding.BinaryUnmarshaler].
 165  func (s *SHA3) UnmarshalBinary(data []byte) error {
 166  	return s.s.UnmarshalBinary(data)
 167  }
 168  
 169  // Clone implements [hash.Cloner].
 170  func (d *SHA3) Clone() (hash.Cloner, error) {
 171  	r := *d
 172  	return &r, nil
 173  }
 174  
 175  // SHAKE is an instance of a SHAKE extendable output function.
 176  type SHAKE struct {
 177  	s sha3.SHAKE
 178  }
 179  
 180  // NewSHAKE128 creates a new SHAKE128 XOF.
 181  func NewSHAKE128() *SHAKE {
 182  	return &SHAKE{*sha3.NewShake128()}
 183  }
 184  
 185  // NewSHAKE256 creates a new SHAKE256 XOF.
 186  func NewSHAKE256() *SHAKE {
 187  	return &SHAKE{*sha3.NewShake256()}
 188  }
 189  
 190  // NewCSHAKE128 creates a new cSHAKE128 XOF.
 191  //
 192  // N is used to define functions based on cSHAKE, it can be empty when plain
 193  // cSHAKE is desired. S is a customization byte string used for domain
 194  // separation. When N and S are both empty, this is equivalent to NewSHAKE128.
 195  func NewCSHAKE128(N, S []byte) *SHAKE {
 196  	return &SHAKE{*sha3.NewCShake128(N, S)}
 197  }
 198  
 199  // NewCSHAKE256 creates a new cSHAKE256 XOF.
 200  //
 201  // N is used to define functions based on cSHAKE, it can be empty when plain
 202  // cSHAKE is desired. S is a customization byte string used for domain
 203  // separation. When N and S are both empty, this is equivalent to NewSHAKE256.
 204  func NewCSHAKE256(N, S []byte) *SHAKE {
 205  	return &SHAKE{*sha3.NewCShake256(N, S)}
 206  }
 207  
 208  // Write absorbs more data into the XOF's state.
 209  //
 210  // It panics if any output has already been read.
 211  func (s *SHAKE) Write(p []byte) (n int, err error) {
 212  	return s.s.Write(p)
 213  }
 214  
 215  // Read squeezes more output from the XOF.
 216  //
 217  // Any call to Write after a call to Read will panic.
 218  func (s *SHAKE) Read(p []byte) (n int, err error) {
 219  	return s.s.Read(p)
 220  }
 221  
 222  // Reset resets the XOF to its initial state.
 223  func (s *SHAKE) Reset() {
 224  	s.s.Reset()
 225  }
 226  
 227  // BlockSize returns the rate of the XOF.
 228  func (s *SHAKE) BlockSize() int {
 229  	return s.s.BlockSize()
 230  }
 231  
 232  // MarshalBinary implements [encoding.BinaryMarshaler].
 233  func (s *SHAKE) MarshalBinary() ([]byte, error) {
 234  	return s.s.MarshalBinary()
 235  }
 236  
 237  // AppendBinary implements [encoding.BinaryAppender].
 238  func (s *SHAKE) AppendBinary(p []byte) ([]byte, error) {
 239  	return s.s.AppendBinary(p)
 240  }
 241  
 242  // UnmarshalBinary implements [encoding.BinaryUnmarshaler].
 243  func (s *SHAKE) UnmarshalBinary(data []byte) error {
 244  	return s.s.UnmarshalBinary(data)
 245  }
 246