Skip to content

Commit

Permalink
use standardized hash.CloneHash interface
Browse files Browse the repository at this point in the history
  • Loading branch information
qmuntal committed Jan 7, 2025
1 parent f7a768e commit bd38c82
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 16 deletions.
30 changes: 24 additions & 6 deletions cng/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,19 @@ func hashToID(h hash.Hash) string {
return hx.alg.id
}

// cloneHash is an interface that defines a Clone method.
//
// hahs.CloneHash will probably be added in Go 1.25, see https://golang.org/issue/69521,
// but we need it now.
type cloneHash interface {
hash.Hash
// Clone returns a separate Hash instance with the same state as h.
Clone() hash.Hash
}

var _ hash.Hash = (*hashX)(nil)
var _ cloneHash = (*hashX)(nil)

// hashX implements [hash.Hash].
type hashX struct {
alg *hashAlgorithm
Expand Down Expand Up @@ -187,17 +200,14 @@ func (h *hashX) init() {
runtime.SetFinalizer(h, (*hashX).finalize)
}

func (h *hashX) Clone() (hash.Hash, error) {
func (h *hashX) Clone() hash.Hash {
defer runtime.KeepAlive(h)
h2 := &hashX{alg: h.alg, key: bytes.Clone(h.key)}
if h.ctx != 0 {
err := bcrypt.DuplicateHash(h.ctx, &h2.ctx, nil, 0)
if err != nil {
return nil, err
}
hashClone(h.ctx, &h2.ctx)
runtime.SetFinalizer(h2, (*hashX).finalize)
}
return h2, nil
return h2
}

func (h *hashX) Reset() {
Expand Down Expand Up @@ -292,3 +302,11 @@ func hashReset(ctx bcrypt.HASH_HANDLE, size int) {
panic(err)
}
}

// hashClone clones ctx into ctx2. It panics on error.
func hashClone(ctx bcrypt.HASH_HANDLE, ctx2 *bcrypt.HASH_HANDLE) {
err := bcrypt.DuplicateHash(ctx, ctx2, nil, 0)
if err != nil {
panic(err)
}
}
5 changes: 1 addition & 4 deletions cng/hash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,7 @@ func TestHash(t *testing.T) {
t.Error("Write didn't change internal hash state")
}

h2, err := h.(interface{ Clone() (hash.Hash, error) }).Clone()
if err != nil {
t.Fatal(err)
}
h2 := h.(interface{ Clone() hash.Hash }).Clone()
h.Write(msg)
h2.Write(msg)
if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) {
Expand Down
10 changes: 4 additions & 6 deletions cng/sha3.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func SupportsSHAKE256() bool {
}

var _ hash.Hash = (*DigestSHA3)(nil)
var _ cloneHash = (*DigestSHA3)(nil)

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

func (h *DigestSHA3) Clone() (hash.Hash, error) {
func (h *DigestSHA3) Clone() hash.Hash {
defer runtime.KeepAlive(h)
h2 := &DigestSHA3{alg: h.alg}
if h.ctx != 0 {
err := bcrypt.DuplicateHash(h.ctx, &h2.ctx, nil, 0)
if err != nil {
return nil, err
}
hashClone(h.ctx, &h2.ctx)
runtime.SetFinalizer(h2, (*DigestSHA3).finalize)
}
return h2, nil
return h2
}

func (h *DigestSHA3) Reset() {
Expand Down

0 comments on commit bd38c82

Please sign in to comment.