mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
crypto/hmac: wrap ErrUnsupported returned by Clone
Updates #69521 Change-Id: I6a6a4656403b9d35d5e4641b5c5c4975f3fa0e43 Reviewed-on: https://go-review.googlesource.com/c/go/+/675555 Reviewed-by: Austin Clements <austin@google.com> Auto-Submit: Filippo Valsorda <filippo@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
parent
03ad694dcb
commit
4731832342
3 changed files with 32 additions and 8 deletions
|
|
@ -11,6 +11,7 @@ import (
|
|||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"testing"
|
||||
|
|
@ -583,6 +584,18 @@ func TestHMAC(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestNoClone(t *testing.T) {
|
||||
h := New(func() hash.Hash { return justHash{sha256.New()} }, []byte("key"))
|
||||
if _, ok := h.(hash.Cloner); !ok {
|
||||
t.Skip("no Cloner support")
|
||||
}
|
||||
h.Write([]byte("test"))
|
||||
_, err := h.(hash.Cloner).Clone()
|
||||
if !errors.Is(err, errors.ErrUnsupported) {
|
||||
t.Errorf("Clone() = %v, want ErrUnsupported", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonUniqueHash(t *testing.T) {
|
||||
if boring.Enabled {
|
||||
t.Skip("hash.Hash provided by boringcrypto are not comparable")
|
||||
|
|
|
|||
|
|
@ -130,26 +130,36 @@ func (h *HMAC) Reset() {
|
|||
h.marshaled = true
|
||||
}
|
||||
|
||||
type errCloneUnsupported struct{}
|
||||
|
||||
func (e errCloneUnsupported) Error() string {
|
||||
return "crypto/hmac: hash does not support hash.Cloner"
|
||||
}
|
||||
|
||||
func (e errCloneUnsupported) Unwrap() error {
|
||||
return errors.ErrUnsupported
|
||||
}
|
||||
|
||||
// Clone implements [hash.Cloner] if the underlying hash does.
|
||||
// Otherwise, it returns [errors.ErrUnsupported].
|
||||
// Otherwise, it returns an error wrapping [errors.ErrUnsupported].
|
||||
func (h *HMAC) Clone() (hash.Cloner, error) {
|
||||
r := *h
|
||||
ic, ok := h.inner.(hash.Cloner)
|
||||
if !ok {
|
||||
return nil, errors.ErrUnsupported
|
||||
return nil, errCloneUnsupported{}
|
||||
}
|
||||
oc, ok := h.outer.(hash.Cloner)
|
||||
if !ok {
|
||||
return nil, errors.ErrUnsupported
|
||||
return nil, errCloneUnsupported{}
|
||||
}
|
||||
var err error
|
||||
r.inner, err = ic.Clone()
|
||||
if err != nil {
|
||||
return nil, errors.ErrUnsupported
|
||||
return nil, errCloneUnsupported{}
|
||||
}
|
||||
r.outer, err = oc.Clone()
|
||||
if err != nil {
|
||||
return nil, errors.ErrUnsupported
|
||||
return nil, errCloneUnsupported{}
|
||||
}
|
||||
return &r, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,13 +57,14 @@ type Hash64 interface {
|
|||
Sum64() uint64
|
||||
}
|
||||
|
||||
// A Cloner is a hash function whose state can be cloned.
|
||||
// A Cloner is a hash function whose state can be cloned, returning a value with
|
||||
// equivalent and independent state.
|
||||
//
|
||||
// All [Hash] implementations in the standard library implement this interface,
|
||||
// unless GOFIPS140=v1.0.0 is set.
|
||||
//
|
||||
// If a hash can only determine at runtime if it can be cloned,
|
||||
// (e.g., if it wraps another hash), it may return [errors.ErrUnsupported].
|
||||
// If a hash can only determine at runtime if it can be cloned (e.g. if it wraps
|
||||
// another hash), it may return an error wrapping [errors.ErrUnsupported].
|
||||
type Cloner interface {
|
||||
Hash
|
||||
Clone() (Cloner, error)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue