1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
package jws
import (
"crypto/hmac"
"crypto/sha256"
"crypto/sha512"
"fmt"
"hash"
"github.com/lestrrat-go/jwx/v2/internal/keyconv"
"github.com/lestrrat-go/jwx/v2/jwa"
)
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, fmt.Errorf(`failed to write payload using hmac: %w`, err)
}
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, fmt.Errorf(`invalid key type %T. []byte is required: %w`, key, err)
}
if len(hmackey) == 0 {
return nil, fmt.Errorf(`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 fmt.Errorf(`failed to generated signature: %w`, err)
}
if !hmac.Equal(signature, expected) {
return fmt.Errorf(`failed to match hmac signature`)
}
return nil
}
|