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 }