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