@@ -148,6 +148,19 @@ func hashToID(h hash.Hash) string {
148148 return hx .alg .id
149149}
150150
151+ // cloneHash is an interface that defines a Clone method.
152+ //
153+ // hash.CloneHash will probably be added in Go 1.25, see https://golang.org/issue/69521,
154+ // but we need it now.
155+ type cloneHash interface {
156+ hash.Hash
157+ // Clone returns a separate Hash instance with the same state as h.
158+ Clone () hash.Hash
159+ }
160+
161+ var _ hash.Hash = (* hashX )(nil )
162+ var _ cloneHash = (* hashX )(nil )
163+
151164// hashX implements [hash.Hash].
152165type hashX struct {
153166 alg * hashAlgorithm
@@ -187,17 +200,14 @@ func (h *hashX) init() {
187200 runtime .SetFinalizer (h , (* hashX ).finalize )
188201}
189202
190- func (h * hashX ) Clone () ( hash.Hash , error ) {
203+ func (h * hashX ) Clone () hash.Hash {
191204 defer runtime .KeepAlive (h )
192205 h2 := & hashX {alg : h .alg , key : bytes .Clone (h .key )}
193206 if h .ctx != 0 {
194- err := bcrypt .DuplicateHash (h .ctx , & h2 .ctx , nil , 0 )
195- if err != nil {
196- return nil , err
197- }
207+ hashClone (h .ctx , & h2 .ctx )
198208 runtime .SetFinalizer (h2 , (* hashX ).finalize )
199209 }
200- return h2 , nil
210+ return h2
201211}
202212
203213func (h * hashX ) Reset () {
@@ -292,3 +302,11 @@ func hashReset(ctx bcrypt.HASH_HANDLE, size int) {
292302 panic (err )
293303 }
294304}
305+
306+ // hashClone clones ctx into ctx2. It panics on error.
307+ func hashClone (ctx bcrypt.HASH_HANDLE , ctx2 * bcrypt.HASH_HANDLE ) {
308+ err := bcrypt .DuplicateHash (ctx , ctx2 , nil , 0 )
309+ if err != nil {
310+ panic (err )
311+ }
312+ }
0 commit comments