gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

hmac.go (2454B)


      1 package jwt
      2 
      3 import (
      4 	"crypto"
      5 	"crypto/hmac"
      6 	"errors"
      7 )
      8 
      9 // Implements the HMAC-SHA family of signing methods signing methods
     10 // Expects key type of []byte for both signing and validation
     11 type SigningMethodHMAC struct {
     12 	Name string
     13 	Hash crypto.Hash
     14 }
     15 
     16 // Specific instances for HS256 and company
     17 var (
     18 	SigningMethodHS256  *SigningMethodHMAC
     19 	SigningMethodHS384  *SigningMethodHMAC
     20 	SigningMethodHS512  *SigningMethodHMAC
     21 	ErrSignatureInvalid = errors.New("signature is invalid")
     22 )
     23 
     24 func init() {
     25 	// HS256
     26 	SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256}
     27 	RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod {
     28 		return SigningMethodHS256
     29 	})
     30 
     31 	// HS384
     32 	SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384}
     33 	RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod {
     34 		return SigningMethodHS384
     35 	})
     36 
     37 	// HS512
     38 	SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512}
     39 	RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod {
     40 		return SigningMethodHS512
     41 	})
     42 }
     43 
     44 func (m *SigningMethodHMAC) Alg() string {
     45 	return m.Name
     46 }
     47 
     48 // Verify the signature of HSXXX tokens.  Returns nil if the signature is valid.
     49 func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error {
     50 	// Verify the key is the right type
     51 	keyBytes, ok := key.([]byte)
     52 	if !ok {
     53 		return ErrInvalidKeyType
     54 	}
     55 
     56 	// Decode signature, for comparison
     57 	sig, err := DecodeSegment(signature)
     58 	if err != nil {
     59 		return err
     60 	}
     61 
     62 	// Can we use the specified hashing method?
     63 	if !m.Hash.Available() {
     64 		return ErrHashUnavailable
     65 	}
     66 
     67 	// This signing method is symmetric, so we validate the signature
     68 	// by reproducing the signature from the signing string and key, then
     69 	// comparing that against the provided signature.
     70 	hasher := hmac.New(m.Hash.New, keyBytes)
     71 	hasher.Write([]byte(signingString))
     72 	if !hmac.Equal(sig, hasher.Sum(nil)) {
     73 		return ErrSignatureInvalid
     74 	}
     75 
     76 	// No validation errors.  Signature is good.
     77 	return nil
     78 }
     79 
     80 // Implements the Sign method from SigningMethod for this signing method.
     81 // Key must be []byte
     82 func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) {
     83 	if keyBytes, ok := key.([]byte); ok {
     84 		if !m.Hash.Available() {
     85 			return "", ErrHashUnavailable
     86 		}
     87 
     88 		hasher := hmac.New(m.Hash.New, keyBytes)
     89 		hasher.Write([]byte(signingString))
     90 
     91 		return EncodeSegment(hasher.Sum(nil)), nil
     92 	}
     93 
     94 	return "", ErrInvalidKeyType
     95 }