Source file src/crypto/sha3/sha3.go

     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 := make([]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 = make([]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 := make([]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 = make([]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  // The zero value is a usable SHA3-256 hash.
   101  type SHA3 struct {
   102  	s sha3.Digest
   103  }
   104  
   105  //go:linkname fips140hash_sha3Unwrap crypto/internal/fips140hash.sha3Unwrap
   106  func fips140hash_sha3Unwrap(sha3 *SHA3) *sha3.Digest {
   107  	return &sha3.s
   108  }
   109  
   110  // New224 creates a new SHA3-224 hash.
   111  func New224() *SHA3 {
   112  	return &SHA3{*sha3.New224()}
   113  }
   114  
   115  // New256 creates a new SHA3-256 hash.
   116  func New256() *SHA3 {
   117  	return &SHA3{*sha3.New256()}
   118  }
   119  
   120  // New384 creates a new SHA3-384 hash.
   121  func New384() *SHA3 {
   122  	return &SHA3{*sha3.New384()}
   123  }
   124  
   125  // New512 creates a new SHA3-512 hash.
   126  func New512() *SHA3 {
   127  	return &SHA3{*sha3.New512()}
   128  }
   129  
   130  func (s *SHA3) init() {
   131  	if s.s.Size() == 0 {
   132  		*s = *New256()
   133  	}
   134  }
   135  
   136  // Write absorbs more data into the hash's state.
   137  func (s *SHA3) Write(p []byte) (n int, err error) {
   138  	s.init()
   139  	return s.s.Write(p)
   140  }
   141  
   142  // Sum appends the current hash to b and returns the resulting slice.
   143  func (s *SHA3) Sum(b []byte) []byte {
   144  	s.init()
   145  	return s.s.Sum(b)
   146  }
   147  
   148  // Reset resets the hash to its initial state.
   149  func (s *SHA3) Reset() {
   150  	s.init()
   151  	s.s.Reset()
   152  }
   153  
   154  // Size returns the number of bytes Sum will produce.
   155  func (s *SHA3) Size() int {
   156  	s.init()
   157  	return s.s.Size()
   158  }
   159  
   160  // BlockSize returns the hash's rate.
   161  func (s *SHA3) BlockSize() int {
   162  	s.init()
   163  	return s.s.BlockSize()
   164  }
   165  
   166  // MarshalBinary implements [encoding.BinaryMarshaler].
   167  func (s *SHA3) MarshalBinary() ([]byte, error) {
   168  	s.init()
   169  	return s.s.MarshalBinary()
   170  }
   171  
   172  // AppendBinary implements [encoding.BinaryAppender].
   173  func (s *SHA3) AppendBinary(p []byte) ([]byte, error) {
   174  	s.init()
   175  	return s.s.AppendBinary(p)
   176  }
   177  
   178  // UnmarshalBinary implements [encoding.BinaryUnmarshaler].
   179  func (s *SHA3) UnmarshalBinary(data []byte) error {
   180  	s.init()
   181  	return s.s.UnmarshalBinary(data)
   182  }
   183  
   184  // Clone implements [hash.Cloner].
   185  func (d *SHA3) Clone() (hash.Cloner, error) {
   186  	r := *d
   187  	return &r, nil
   188  }
   189  
   190  // SHAKE is an instance of a SHAKE extendable output function.
   191  // The zero value is a usable SHAKE256 hash.
   192  type SHAKE struct {
   193  	s sha3.SHAKE
   194  }
   195  
   196  func (s *SHAKE) init() {
   197  	if s.s.Size() == 0 {
   198  		*s = *NewSHAKE256()
   199  	}
   200  }
   201  
   202  // NewSHAKE128 creates a new SHAKE128 XOF.
   203  func NewSHAKE128() *SHAKE {
   204  	return &SHAKE{*sha3.NewShake128()}
   205  }
   206  
   207  // NewSHAKE256 creates a new SHAKE256 XOF.
   208  func NewSHAKE256() *SHAKE {
   209  	return &SHAKE{*sha3.NewShake256()}
   210  }
   211  
   212  // NewCSHAKE128 creates a new cSHAKE128 XOF.
   213  //
   214  // N is used to define functions based on cSHAKE, it can be empty when plain
   215  // cSHAKE is desired. S is a customization byte string used for domain
   216  // separation. When N and S are both empty, this is equivalent to NewSHAKE128.
   217  func NewCSHAKE128(N, S []byte) *SHAKE {
   218  	return &SHAKE{*sha3.NewCShake128(N, S)}
   219  }
   220  
   221  // NewCSHAKE256 creates a new cSHAKE256 XOF.
   222  //
   223  // N is used to define functions based on cSHAKE, it can be empty when plain
   224  // cSHAKE is desired. S is a customization byte string used for domain
   225  // separation. When N and S are both empty, this is equivalent to NewSHAKE256.
   226  func NewCSHAKE256(N, S []byte) *SHAKE {
   227  	return &SHAKE{*sha3.NewCShake256(N, S)}
   228  }
   229  
   230  // Write absorbs more data into the XOF's state.
   231  //
   232  // It panics if any output has already been read.
   233  func (s *SHAKE) Write(p []byte) (n int, err error) {
   234  	s.init()
   235  	return s.s.Write(p)
   236  }
   237  
   238  // Read squeezes more output from the XOF.
   239  //
   240  // Any call to Write after a call to Read will panic.
   241  func (s *SHAKE) Read(p []byte) (n int, err error) {
   242  	s.init()
   243  	return s.s.Read(p)
   244  }
   245  
   246  // Reset resets the XOF to its initial state.
   247  func (s *SHAKE) Reset() {
   248  	s.init()
   249  	s.s.Reset()
   250  }
   251  
   252  // BlockSize returns the rate of the XOF.
   253  func (s *SHAKE) BlockSize() int {
   254  	s.init()
   255  	return s.s.BlockSize()
   256  }
   257  
   258  // MarshalBinary implements [encoding.BinaryMarshaler].
   259  func (s *SHAKE) MarshalBinary() ([]byte, error) {
   260  	s.init()
   261  	return s.s.MarshalBinary()
   262  }
   263  
   264  // AppendBinary implements [encoding.BinaryAppender].
   265  func (s *SHAKE) AppendBinary(p []byte) ([]byte, error) {
   266  	s.init()
   267  	return s.s.AppendBinary(p)
   268  }
   269  
   270  // UnmarshalBinary implements [encoding.BinaryUnmarshaler].
   271  func (s *SHAKE) UnmarshalBinary(data []byte) error {
   272  	s.init()
   273  	return s.s.UnmarshalBinary(data)
   274  }
   275  

View as plain text