auth/vendor/github.com/lestrrat-go/jwx/jws/hmac.go

78 lines
1.8 KiB
Go

package jws
import (
"crypto/hmac"
"crypto/sha256"
"crypto/sha512"
"hash"
"github.com/lestrrat-go/jwx/internal/keyconv"
"github.com/lestrrat-go/jwx/jwa"
"github.com/pkg/errors"
)
var hmacSignFuncs = map[jwa.SignatureAlgorithm]hmacSignFunc{}
func init() {
algs := map[jwa.SignatureAlgorithm]func() hash.Hash{
jwa.HS256: sha256.New,
jwa.HS384: sha512.New384,
jwa.HS512: sha512.New,
}
for alg, h := range algs {
hmacSignFuncs[alg] = makeHMACSignFunc(h)
}
}
func newHMACSigner(alg jwa.SignatureAlgorithm) Signer {
return &HMACSigner{
alg: alg,
sign: hmacSignFuncs[alg], // we know this will succeed
}
}
func makeHMACSignFunc(hfunc func() hash.Hash) hmacSignFunc {
return func(payload []byte, key []byte) ([]byte, error) {
h := hmac.New(hfunc, key)
if _, err := h.Write(payload); err != nil {
return nil, errors.Wrap(err, "failed to write payload using hmac")
}
return h.Sum(nil), nil
}
}
func (s HMACSigner) Algorithm() jwa.SignatureAlgorithm {
return s.alg
}
func (s HMACSigner) Sign(payload []byte, key interface{}) ([]byte, error) {
var hmackey []byte
if err := keyconv.ByteSliceKey(&hmackey, key); err != nil {
return nil, errors.Wrapf(err, `invalid key type %T. []byte is required`, key)
}
if len(hmackey) == 0 {
return nil, errors.New(`missing key while signing payload`)
}
return s.sign(payload, hmackey)
}
func newHMACVerifier(alg jwa.SignatureAlgorithm) Verifier {
s := newHMACSigner(alg)
return &HMACVerifier{signer: s}
}
func (v HMACVerifier) Verify(payload, signature []byte, key interface{}) (err error) {
expected, err := v.signer.Sign(payload, key)
if err != nil {
return errors.Wrap(err, `failed to generated signature`)
}
if !hmac.Equal(signature, expected) {
return errors.New(`failed to match hmac signature`)
}
return nil
}