Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.4 KiB
95 lines
2.4 KiB
package jwt |
|
|
|
import ( |
|
"crypto" |
|
"crypto/hmac" |
|
"errors" |
|
) |
|
|
|
// Implements the HMAC-SHA family of signing methods signing methods |
|
// Expects key type of []byte for both signing and validation |
|
type SigningMethodHMAC struct { |
|
Name string |
|
Hash crypto.Hash |
|
} |
|
|
|
// Specific instances for HS256 and company |
|
var ( |
|
SigningMethodHS256 *SigningMethodHMAC |
|
SigningMethodHS384 *SigningMethodHMAC |
|
SigningMethodHS512 *SigningMethodHMAC |
|
ErrSignatureInvalid = errors.New("signature is invalid") |
|
) |
|
|
|
func init() { |
|
// HS256 |
|
SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256} |
|
RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod { |
|
return SigningMethodHS256 |
|
}) |
|
|
|
// HS384 |
|
SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384} |
|
RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod { |
|
return SigningMethodHS384 |
|
}) |
|
|
|
// HS512 |
|
SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512} |
|
RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod { |
|
return SigningMethodHS512 |
|
}) |
|
} |
|
|
|
func (m *SigningMethodHMAC) Alg() string { |
|
return m.Name |
|
} |
|
|
|
// Verify the signature of HSXXX tokens. Returns nil if the signature is valid. |
|
func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { |
|
// Verify the key is the right type |
|
keyBytes, ok := key.([]byte) |
|
if !ok { |
|
return ErrInvalidKeyType |
|
} |
|
|
|
// Decode signature, for comparison |
|
sig, err := DecodeSegment(signature) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// Can we use the specified hashing method? |
|
if !m.Hash.Available() { |
|
return ErrHashUnavailable |
|
} |
|
|
|
// This signing method is symmetric, so we validate the signature |
|
// by reproducing the signature from the signing string and key, then |
|
// comparing that against the provided signature. |
|
hasher := hmac.New(m.Hash.New, keyBytes) |
|
hasher.Write([]byte(signingString)) |
|
if !hmac.Equal(sig, hasher.Sum(nil)) { |
|
return ErrSignatureInvalid |
|
} |
|
|
|
// No validation errors. Signature is good. |
|
return nil |
|
} |
|
|
|
// Implements the Sign method from SigningMethod for this signing method. |
|
// Key must be []byte |
|
func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { |
|
if keyBytes, ok := key.([]byte); ok { |
|
if !m.Hash.Available() { |
|
return "", ErrHashUnavailable |
|
} |
|
|
|
hasher := hmac.New(m.Hash.New, keyBytes) |
|
hasher.Write([]byte(signingString)) |
|
|
|
return EncodeSegment(hasher.Sum(nil)), nil |
|
} |
|
|
|
return "", ErrInvalidKeyType |
|
}
|
|
|