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 if d.dsbyte == dsbyteKeccak {
148 fips140.RecordNonApproved()
149 } else {
150 fips140.RecordApproved()
151 }
152 return d.sum(b)
153 }
154
155 func (d *Digest) sumGeneric(b []byte) []byte {
156 if d.state != spongeAbsorbing {
157 panic("sha3: Sum after Read")
158 }
159
160
161
162 dup := d.Clone()
163 hash := make([]byte, dup.outputLen, 64)
164 dup.read(hash)
165 return append(b, hash...)
166 }
167
168 const (
169 magicSHA3 = "sha\x08"
170 magicShake = "sha\x09"
171 magicCShake = "sha\x0a"
172 magicKeccak = "sha\x0b"
173
174 marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
175 )
176
177 func (d *Digest) MarshalBinary() ([]byte, error) {
178 return d.AppendBinary(make([]byte, 0, marshaledSize))
179 }
180
181 func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
182 switch d.dsbyte {
183 case dsbyteSHA3:
184 b = append(b, magicSHA3...)
185 case dsbyteShake:
186 b = append(b, magicShake...)
187 case dsbyteCShake:
188 b = append(b, magicCShake...)
189 case dsbyteKeccak:
190 b = append(b, magicKeccak...)
191 default:
192 panic("unknown dsbyte")
193 }
194
195 b = append(b, byte(d.rate))
196 b = append(b, d.a[:]...)
197 b = append(b, byte(d.n), byte(d.state))
198 return b, nil
199 }
200
201 func (d *Digest) UnmarshalBinary(b []byte) error {
202 if len(b) != marshaledSize {
203 return errors.New("sha3: invalid hash state")
204 }
205
206 magic := string(b[:len(magicSHA3)])
207 b = b[len(magicSHA3):]
208 switch {
209 case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
210 case magic == magicShake && d.dsbyte == dsbyteShake:
211 case magic == magicCShake && d.dsbyte == dsbyteCShake:
212 case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
213 default:
214 return errors.New("sha3: invalid hash state identifier")
215 }
216
217 rate := int(b[0])
218 b = b[1:]
219 if rate != d.rate {
220 return errors.New("sha3: invalid hash state function")
221 }
222
223 copy(d.a[:], b)
224 b = b[len(d.a):]
225
226 n, state := int(b[0]), spongeDirection(b[1])
227 if n > d.rate {
228 return errors.New("sha3: invalid hash state")
229 }
230 d.n = n
231 if state != spongeAbsorbing && state != spongeSqueezing {
232 return errors.New("sha3: invalid hash state")
233 }
234 d.state = state
235
236 return nil
237 }
238
View as plain text