Skip to content

Commit bd38c82

Browse files
committed
use standardized hash.CloneHash interface
1 parent f7a768e commit bd38c82

File tree

3 files changed

+29
-16
lines changed

3 files changed

+29
-16
lines changed

cng/hash.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
// hahs.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].
152165
type 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

203213
func (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+
}

cng/hash_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,7 @@ func TestHash(t *testing.T) {
7979
t.Error("Write didn't change internal hash state")
8080
}
8181

82-
h2, err := h.(interface{ Clone() (hash.Hash, error) }).Clone()
83-
if err != nil {
84-
t.Fatal(err)
85-
}
82+
h2 := h.(interface{ Clone() hash.Hash }).Clone()
8683
h.Write(msg)
8784
h2.Write(msg)
8885
if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) {

cng/sha3.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ func SupportsSHAKE256() bool {
7373
}
7474

7575
var _ hash.Hash = (*DigestSHA3)(nil)
76+
var _ cloneHash = (*DigestSHA3)(nil)
7677

7778
// DigestSHA3 is the [sha3.SHA3] implementation using the CNG API.
7879
type DigestSHA3 struct {
@@ -111,17 +112,14 @@ func (h *DigestSHA3) init() {
111112
runtime.SetFinalizer(h, (*DigestSHA3).finalize)
112113
}
113114

114-
func (h *DigestSHA3) Clone() (hash.Hash, error) {
115+
func (h *DigestSHA3) Clone() hash.Hash {
115116
defer runtime.KeepAlive(h)
116117
h2 := &DigestSHA3{alg: h.alg}
117118
if h.ctx != 0 {
118-
err := bcrypt.DuplicateHash(h.ctx, &h2.ctx, nil, 0)
119-
if err != nil {
120-
return nil, err
121-
}
119+
hashClone(h.ctx, &h2.ctx)
122120
runtime.SetFinalizer(h2, (*DigestSHA3).finalize)
123121
}
124-
return h2, nil
122+
return h2
125123
}
126124

127125
func (h *DigestSHA3) Reset() {

0 commit comments

Comments
 (0)