1
2
3
4
5
6
7
8
9
10
11 package sha3
12
13 import (
14 "crypto/internal/fips140"
15 "crypto/internal/fips140/subtle"
16 "errors"
17 )
18
19
20 type spongeDirection int
21
22 const (
23
24 spongeAbsorbing spongeDirection = iota
25
26 spongeSqueezing
27 )
28
29 type Digest struct {
30 a [1600 / 8]byte
31
32
33
34
35 n, rate int
36
37
38
39
40
41
42
43
44
45
46
47
48
49 dsbyte byte
50
51 outputLen int
52 state spongeDirection
53 }
54
55
56 func (d *Digest) BlockSize() int { return d.rate }
57
58
59 func (d *Digest) Size() int { return d.outputLen }
60
61
62 func (d *Digest) Reset() {
63
64 clear(d.a[:])
65 d.state = spongeAbsorbing
66 d.n = 0
67 }
68
69 func (d *Digest) Clone() *Digest {
70 ret := *d
71 return &ret
72 }
73
74
75 func (d *Digest) permute() {
76 keccakF1600(&d.a)
77 d.n = 0
78 }
79
80
81
82 func (d *Digest) padAndPermute() {
83
84
85
86
87 d.a[d.n] ^= d.dsbyte
88
89
90
91 d.a[d.rate-1] ^= 0x80
92
93 d.permute()
94 d.state = spongeSqueezing
95 }
96
97
98 func (d *Digest) Write(p []byte) (n int, err error) { return d.write(p) }
99 func (d *Digest) writeGeneric(p []byte) (n int, err error) {
100 if d.state != spongeAbsorbing {
101 panic("sha3: Write after Read")
102 }
103
104 n = len(p)
105
106 for len(p) > 0 {
107 x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
108 d.n += x
109 p = p[x:]
110
111
112 if d.n == d.rate {
113 d.permute()
114 }
115 }
116
117 return
118 }
119
120
121 func (d *Digest) readGeneric(out []byte) (n int, err error) {
122
123 if d.state == spongeAbsorbing {
124 d.padAndPermute()
125 }
126
127 n = len(out)
128
129
130 for len(out) > 0 {
131
132 if d.n == d.rate {
133 d.permute()
134 }
135
136 x := copy(out, d.a[d.n:d.rate])
137 d.n += x
138 out = out[x:]
139 }
140
141 return
142 }
143
144
145
146 func (d *Digest) Sum(b []byte) []byte {
147 fips140.RecordApproved()
148 return d.sum(b)
149 }
150
151 func (d *Digest) sumGeneric(b []byte) []byte {
152 if d.state != spongeAbsorbing {
153 panic("sha3: Sum after Read")
154 }
155
156
157
158 dup := d.Clone()
159 hash := make([]byte, dup.outputLen, 64)
160 dup.read(hash)
161 return append(b, hash...)
162 }
163
164 const (
165 magicSHA3 = "sha\x08"
166 magicShake = "sha\x09"
167 magicCShake = "sha\x0a"
168 magicKeccak = "sha\x0b"
169
170 marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
171 )
172
173 func (d *Digest) MarshalBinary() ([]byte, error) {
174 return d.AppendBinary(make([]byte, 0, marshaledSize))
175 }
176
177 func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
178 switch d.dsbyte {
179 case dsbyteSHA3:
180 b = append(b, magicSHA3...)
181 case dsbyteShake:
182 b = append(b, magicShake...)
183 case dsbyteCShake:
184 b = append(b, magicCShake...)
185 case dsbyteKeccak:
186 b = append(b, magicKeccak...)
187 default:
188 panic("unknown dsbyte")
189 }
190
191 b = append(b, byte(d.rate))
192 b = append(b, d.a[:]...)
193 b = append(b, byte(d.n), byte(d.state))
194 return b, nil
195 }
196
197 func (d *Digest) UnmarshalBinary(b []byte) error {
198 if len(b) != marshaledSize {
199 return errors.New("sha3: invalid hash state")
200 }
201
202 magic := string(b[:len(magicSHA3)])
203 b = b[len(magicSHA3):]
204 switch {
205 case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
206 case magic == magicShake && d.dsbyte == dsbyteShake:
207 case magic == magicCShake && d.dsbyte == dsbyteCShake:
208 case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
209 default:
210 return errors.New("sha3: invalid hash state identifier")
211 }
212
213 rate := int(b[0])
214 b = b[1:]
215 if rate != d.rate {
216 return errors.New("sha3: invalid hash state function")
217 }
218
219 copy(d.a[:], b)
220 b = b[len(d.a):]
221
222 n, state := int(b[0]), spongeDirection(b[1])
223 if n > d.rate {
224 return errors.New("sha3: invalid hash state")
225 }
226 d.n = n
227 if state != spongeAbsorbing && state != spongeSqueezing {
228 return errors.New("sha3: invalid hash state")
229 }
230 d.state = state
231
232 return nil
233 }
234
View as plain text