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
5package sha3
6
7// This implementation is only used for NewLegacyKeccak256 and
8// NewLegacyKeccak512, which are not implemented by crypto/sha3.
9// All other functions in this package are wrappers around crypto/sha3.
10
11import (
12 "crypto/subtle"
13 "encoding/binary"
14 "errors"
15 "hash"
16 "unsafe"
17
18 "golang.org/x/sys/cpu"
19)
20
21const (
22 dsbyteKeccak = 0b00000001
23
24 // rateK[c] is the rate in bytes for Keccak[c] where c is the capacity in
25 // bits. Given the sponge size is 1600 bits, the rate is 1600 - c bits.
26 rateK256 = (1600 - 256) / 8
27 rateK512 = (1600 - 512) / 8
28 rateK1024 = (1600 - 1024) / 8
29)
30
31// NewLegacyKeccak256 creates a new Keccak-256 hash.
32//
33// Only use this function if you require compatibility with an existing cryptosystem
34// that uses non-standard padding. All other users should use New256 instead.
35func NewLegacyKeccak256() hash.Hash {
36 return &state{rate: rateK512, outputLen: 32, dsbyte: dsbyteKeccak}
37}
38
39// NewLegacyKeccak512 creates a new Keccak-512 hash.
40//
41// Only use this function if you require compatibility with an existing cryptosystem
42// that uses non-standard padding. All other users should use New512 instead.
43func NewLegacyKeccak512() hash.Hash {
44 return &state{rate: rateK1024, outputLen: 64, dsbyte: dsbyteKeccak}
45}
46
47// spongeDirection indicates the direction bytes are flowing through the sponge.
48type spongeDirection int
49
50const (
51 // spongeAbsorbing indicates that the sponge is absorbing input.
52 spongeAbsorbing spongeDirection = iota
53 // spongeSqueezing indicates that the sponge is being squeezed.
54 spongeSqueezing
55)
56
57type state struct {
58 a [1600 / 8]byte // main state of the hash
59
60 // a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR
61 // into before running the permutation. If squeezing, it's the remaining
62 // output to produce before running the permutation.
63 n, rate int
64
65 // dsbyte contains the "domain separation" bits and the first bit of
66 // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
67 // SHA-3 and SHAKE functions by appending bitstrings to the message.
68 // Using a little-endian bit-ordering convention, these are "01" for SHA-3
69 // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
70 // padding rule from section 5.1 is applied to pad the message to a multiple
71 // of the rate, which involves adding a "1" bit, zero or more "0" bits, and
72 // a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
73 // giving 00000110b (0x06) and 00011111b (0x1f).
74 // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
75 // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
76 // Extendable-Output Functions (May 2014)"
77 dsbyte byte
78
79 outputLen int // the default output size in bytes
80 state spongeDirection // whether the sponge is absorbing or squeezing
81}
82
83// BlockSize returns the rate of sponge underlying this hash function.
84func (d *state) BlockSize() int { return d.rate }
85
86// Size returns the output size of the hash function in bytes.
87func (d *state) Size() int { return d.outputLen }
88
89// Reset clears the internal state by zeroing the sponge state and
90// the buffer indexes, and setting Sponge.state to absorbing.
91func (d *state) Reset() {
92 // Zero the permutation's state.
93 for i := range d.a {
94 d.a[i] = 0
95 }
96 d.state = spongeAbsorbing
97 d.n = 0
98}
99
100func (d *state) clone() *state {
101 ret := *d
102 return &ret
103}
104
105// permute applies the KeccakF-1600 permutation.
106func (d *state) permute() {
107 var a *[25]uint64
108 if cpu.IsBigEndian {
109 a = new([25]uint64)
110 for i := range a {
111 a[i] = binary.LittleEndian.Uint64(d.a[i*8:])
112 }
113 } else {
114 a = (*[25]uint64)(unsafe.Pointer(&d.a))
115 }
116
117 keccakF1600(a)
118 d.n = 0
119
120 if cpu.IsBigEndian {
121 for i := range a {
122 binary.LittleEndian.PutUint64(d.a[i*8:], a[i])
123 }
124 }
125}
126
127// pads appends the domain separation bits in dsbyte, applies
128// the multi-bitrate 10..1 padding rule, and permutes the state.
129func (d *state) padAndPermute() {
130 // Pad with this instance's domain-separator bits. We know that there's
131 // at least one byte of space in the sponge because, if it were full,
132 // permute would have been called to empty it. dsbyte also contains the
133 // first one bit for the padding. See the comment in the state struct.
134 d.a[d.n] ^= d.dsbyte
135 // This adds the final one bit for the padding. Because of the way that
136 // bits are numbered from the LSB upwards, the final bit is the MSB of
137 // the last byte.
138 d.a[d.rate-1] ^= 0x80
139 // Apply the permutation
140 d.permute()
141 d.state = spongeSqueezing
142}
143
144// Write absorbs more data into the hash's state. It panics if any
145// output has already been read.
146func (d *state) Write(p []byte) (n int, err error) {
147 if d.state != spongeAbsorbing {
148 panic("sha3: Write after Read")
149 }
150
151 n = len(p)
152
153 for len(p) > 0 {
154 x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
155 d.n += x
156 p = p[x:]
157
158 // If the sponge is full, apply the permutation.
159 if d.n == d.rate {
160 d.permute()
161 }
162 }
163
164 return
165}
166
167// Read squeezes an arbitrary number of bytes from the sponge.
168func (d *state) Read(out []byte) (n int, err error) {
169 // If we're still absorbing, pad and apply the permutation.
170 if d.state == spongeAbsorbing {
171 d.padAndPermute()
172 }
173
174 n = len(out)
175
176 // Now, do the squeezing.
177 for len(out) > 0 {
178 // Apply the permutation if we've squeezed the sponge dry.
179 if d.n == d.rate {
180 d.permute()
181 }
182
183 x := copy(out, d.a[d.n:d.rate])
184 d.n += x
185 out = out[x:]
186 }
187
188 return
189}
190
191// Sum applies padding to the hash state and then squeezes out the desired
192// number of output bytes. It panics if any output has already been read.
193func (d *state) Sum(in []byte) []byte {
194 if d.state != spongeAbsorbing {
195 panic("sha3: Sum after Read")
196 }
197
198 // Make a copy of the original hash so that caller can keep writing
199 // and summing.
200 dup := d.clone()
201 hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation
202 dup.Read(hash)
203 return append(in, hash...)
204}
205
206const (
207 magicKeccak = "sha\x0b"
208 // magic || rate || main state || n || sponge direction
209 marshaledSize = len(magicKeccak) + 1 + 200 + 1 + 1
210)
211
212func (d *state) MarshalBinary() ([]byte, error) {
213 return d.AppendBinary(make([]byte, 0, marshaledSize))
214}
215
216func (d *state) AppendBinary(b []byte) ([]byte, error) {
217 switch d.dsbyte {
218 case dsbyteKeccak:
219 b = append(b, magicKeccak...)
220 default:
221 panic("unknown dsbyte")
222 }
223 // rate is at most 168, and n is at most rate.
224 b = append(b, byte(d.rate))
225 b = append(b, d.a[:]...)
226 b = append(b, byte(d.n), byte(d.state))
227 return b, nil
228}
229
230func (d *state) UnmarshalBinary(b []byte) error {
231 if len(b) != marshaledSize {
232 return errors.New("sha3: invalid hash state")
233 }
234
235 magic := string(b[:len(magicKeccak)])
236 b = b[len(magicKeccak):]
237 switch {
238 case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
239 default:
240 return errors.New("sha3: invalid hash state identifier")
241 }
242
243 rate := int(b[0])
244 b = b[1:]
245 if rate != d.rate {
246 return errors.New("sha3: invalid hash state function")
247 }
248
249 copy(d.a[:], b)
250 b = b[len(d.a):]
251
252 n, state := int(b[0]), spongeDirection(b[1])
253 if n > d.rate {
254 return errors.New("sha3: invalid hash state")
255 }
256 d.n = n
257 if state != spongeAbsorbing && state != spongeSqueezing {
258 return errors.New("sha3: invalid hash state")
259 }
260 d.state = state
261
262 return nil
263}