@@ -23,7 +23,6 @@ const (
23
23
type state struct {
24
24
// Generic sponge components.
25
25
a [25 ]uint64 // main state of the hash
26
- buf []byte // points into storage
27
26
rate int // the number of bytes of state to use
28
27
29
28
// dsbyte contains the "domain separation" bits and the first bit of
@@ -40,6 +39,7 @@ type state struct {
40
39
// Extendable-Output Functions (May 2014)"
41
40
dsbyte byte
42
41
42
+ i , n int // storage[i:n] is the buffer, i is only used while squeezing
43
43
storage [maxRate ]byte
44
44
45
45
// Specific to SHA-3 and SHAKE.
@@ -54,24 +54,18 @@ func (d *state) BlockSize() int { return d.rate }
54
54
func (d * state ) Size () int { return d .outputLen }
55
55
56
56
// Reset clears the internal state by zeroing the sponge state and
57
- // the byte buffer, and setting Sponge.state to absorbing.
57
+ // the buffer indexes , and setting Sponge.state to absorbing.
58
58
func (d * state ) Reset () {
59
59
// Zero the permutation's state.
60
60
for i := range d .a {
61
61
d .a [i ] = 0
62
62
}
63
63
d .state = spongeAbsorbing
64
- d .buf = d . storage [: 0 ]
64
+ d .i , d . n = 0 , 0
65
65
}
66
66
67
67
func (d * state ) clone () * state {
68
68
ret := * d
69
- if ret .state == spongeAbsorbing {
70
- ret .buf = ret .storage [:len (ret .buf )]
71
- } else {
72
- ret .buf = ret .storage [d .rate - cap (d .buf ) : d .rate ]
73
- }
74
-
75
69
return & ret
76
70
}
77
71
@@ -82,43 +76,40 @@ func (d *state) permute() {
82
76
case spongeAbsorbing :
83
77
// If we're absorbing, we need to xor the input into the state
84
78
// before applying the permutation.
85
- xorIn (d , d .buf )
86
- d .buf = d . storage [: 0 ]
79
+ xorIn (d , d .storage [: d . rate ] )
80
+ d .n = 0
87
81
keccakF1600 (& d .a )
88
82
case spongeSqueezing :
89
83
// If we're squeezing, we need to apply the permutation before
90
84
// copying more output.
91
85
keccakF1600 (& d .a )
92
- d .buf = d . storage [: d . rate ]
93
- copyOut (d , d .buf )
86
+ d .i = 0
87
+ copyOut (d , d .storage [: d . rate ] )
94
88
}
95
89
}
96
90
97
91
// pads appends the domain separation bits in dsbyte, applies
98
92
// the multi-bitrate 10..1 padding rule, and permutes the state.
99
- func (d * state ) padAndPermute (dsbyte byte ) {
100
- if d .buf == nil {
101
- d .buf = d .storage [:0 ]
102
- }
93
+ func (d * state ) padAndPermute () {
103
94
// Pad with this instance's domain-separator bits. We know that there's
104
95
// at least one byte of space in d.buf because, if it were full,
105
96
// permute would have been called to empty it. dsbyte also contains the
106
97
// first one bit for the padding. See the comment in the state struct.
107
- d .buf = append ( d . buf , dsbyte )
108
- zerosStart := len ( d . buf )
109
- d . buf = d .storage [: d . rate ]
110
- for i := zerosStart ; i < d . rate ; i ++ {
111
- d .buf [ i ] = 0
98
+ d .storage [ d . n ] = d . dsbyte
99
+ d . n ++
100
+ for d . n < d .rate {
101
+ d . storage [ d . n ] = 0
102
+ d .n ++
112
103
}
113
104
// This adds the final one bit for the padding. Because of the way that
114
105
// bits are numbered from the LSB upwards, the final bit is the MSB of
115
106
// the last byte.
116
- d .buf [d .rate - 1 ] ^= 0x80
107
+ d .storage [d .rate - 1 ] ^= 0x80
117
108
// Apply the permutation
118
109
d .permute ()
119
110
d .state = spongeSqueezing
120
- d .buf = d .storage [: d . rate ]
121
- copyOut (d , d .buf )
111
+ d .n = d .rate
112
+ copyOut (d , d .storage [: d . rate ] )
122
113
}
123
114
124
115
// Write absorbs more data into the hash's state. It panics if any
@@ -127,28 +118,25 @@ func (d *state) Write(p []byte) (written int, err error) {
127
118
if d .state != spongeAbsorbing {
128
119
panic ("sha3: Write after Read" )
129
120
}
130
- if d .buf == nil {
131
- d .buf = d .storage [:0 ]
132
- }
133
121
written = len (p )
134
122
135
123
for len (p ) > 0 {
136
- if len ( d . buf ) == 0 && len (p ) >= d .rate {
124
+ if d . n == 0 && len (p ) >= d .rate {
137
125
// The fast path; absorb a full "rate" bytes of input and apply the permutation.
138
126
xorIn (d , p [:d .rate ])
139
127
p = p [d .rate :]
140
128
keccakF1600 (& d .a )
141
129
} else {
142
130
// The slow path; buffer the input until we can fill the sponge, and then xor it in.
143
- todo := d .rate - len ( d . buf )
131
+ todo := d .rate - d . n
144
132
if todo > len (p ) {
145
133
todo = len (p )
146
134
}
147
- d .buf = append (d .buf , p [:todo ]... )
135
+ d .n += copy (d .storage [ d . n :] , p [:todo ])
148
136
p = p [todo :]
149
137
150
138
// If the sponge is full, apply the permutation.
151
- if len ( d . buf ) == d .rate {
139
+ if d . n == d .rate {
152
140
d .permute ()
153
141
}
154
142
}
@@ -161,19 +149,19 @@ func (d *state) Write(p []byte) (written int, err error) {
161
149
func (d * state ) Read (out []byte ) (n int , err error ) {
162
150
// If we're still absorbing, pad and apply the permutation.
163
151
if d .state == spongeAbsorbing {
164
- d .padAndPermute (d . dsbyte )
152
+ d .padAndPermute ()
165
153
}
166
154
167
155
n = len (out )
168
156
169
157
// Now, do the squeezing.
170
158
for len (out ) > 0 {
171
- n := copy (out , d .buf )
172
- d .buf = d . buf [ n :]
159
+ n := copy (out , d .storage [ d . i : d . n ] )
160
+ d .i += n
173
161
out = out [n :]
174
162
175
163
// Apply the permutation if we've squeezed the sponge dry.
176
- if len ( d . buf ) == 0 {
164
+ if d . i == d . rate {
177
165
d .permute ()
178
166
}
179
167
}
0 commit comments