...

Source file src/github.com/lestrrat-go/jwx/jws/hmac.go

Documentation: github.com/lestrrat-go/jwx/jws

     1  package jws
     2  
     3  import (
     4  	"crypto/hmac"
     5  	"crypto/sha256"
     6  	"crypto/sha512"
     7  	"hash"
     8  
     9  	"github.com/lestrrat-go/jwx/internal/keyconv"
    10  	"github.com/lestrrat-go/jwx/jwa"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  var hmacSignFuncs = map[jwa.SignatureAlgorithm]hmacSignFunc{}
    15  
    16  func init() {
    17  	algs := map[jwa.SignatureAlgorithm]func() hash.Hash{
    18  		jwa.HS256: sha256.New,
    19  		jwa.HS384: sha512.New384,
    20  		jwa.HS512: sha512.New,
    21  	}
    22  
    23  	for alg, h := range algs {
    24  		hmacSignFuncs[alg] = makeHMACSignFunc(h)
    25  	}
    26  }
    27  
    28  func newHMACSigner(alg jwa.SignatureAlgorithm) Signer {
    29  	return &HMACSigner{
    30  		alg:  alg,
    31  		sign: hmacSignFuncs[alg], // we know this will succeed
    32  	}
    33  }
    34  
    35  func makeHMACSignFunc(hfunc func() hash.Hash) hmacSignFunc {
    36  	return func(payload []byte, key []byte) ([]byte, error) {
    37  		h := hmac.New(hfunc, key)
    38  		if _, err := h.Write(payload); err != nil {
    39  			return nil, errors.Wrap(err, "failed to write payload using hmac")
    40  		}
    41  		return h.Sum(nil), nil
    42  	}
    43  }
    44  
    45  func (s HMACSigner) Algorithm() jwa.SignatureAlgorithm {
    46  	return s.alg
    47  }
    48  
    49  func (s HMACSigner) Sign(payload []byte, key interface{}) ([]byte, error) {
    50  	var hmackey []byte
    51  	if err := keyconv.ByteSliceKey(&hmackey, key); err != nil {
    52  		return nil, errors.Wrapf(err, `invalid key type %T. []byte is required`, key)
    53  	}
    54  
    55  	if len(hmackey) == 0 {
    56  		return nil, errors.New(`missing key while signing payload`)
    57  	}
    58  
    59  	return s.sign(payload, hmackey)
    60  }
    61  
    62  func newHMACVerifier(alg jwa.SignatureAlgorithm) Verifier {
    63  	s := newHMACSigner(alg)
    64  	return &HMACVerifier{signer: s}
    65  }
    66  
    67  func (v HMACVerifier) Verify(payload, signature []byte, key interface{}) (err error) {
    68  	expected, err := v.signer.Sign(payload, key)
    69  	if err != nil {
    70  		return errors.Wrap(err, `failed to generated signature`)
    71  	}
    72  
    73  	if !hmac.Equal(signature, expected) {
    74  		return errors.New(`failed to match hmac signature`)
    75  	}
    76  	return nil
    77  }
    78  

View as plain text