82 lines
2.0 KiB
Go
82 lines
2.0 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/hmac"
|
|
"encoding/json"
|
|
"errors"
|
|
)
|
|
|
|
// SigningMethodHMAC implements the HMAC-SHA family of SigningMethods.
|
|
type SigningMethodHMAC struct {
|
|
Name string
|
|
Hash crypto.Hash
|
|
_ struct{}
|
|
}
|
|
|
|
// Specific instances of HMAC-SHA SigningMethods.
|
|
var (
|
|
// SigningMethodHS256 implements HS256.
|
|
SigningMethodHS256 = &SigningMethodHMAC{
|
|
Name: "HS256",
|
|
Hash: crypto.SHA256,
|
|
}
|
|
|
|
// SigningMethodHS384 implements HS384.
|
|
SigningMethodHS384 = &SigningMethodHMAC{
|
|
Name: "HS384",
|
|
Hash: crypto.SHA384,
|
|
}
|
|
|
|
// SigningMethodHS512 implements HS512.
|
|
SigningMethodHS512 = &SigningMethodHMAC{
|
|
Name: "HS512",
|
|
Hash: crypto.SHA512,
|
|
}
|
|
|
|
// ErrSignatureInvalid is returned when the provided signature is found
|
|
// to be invalid.
|
|
ErrSignatureInvalid = errors.New("signature is invalid")
|
|
)
|
|
|
|
// Alg implements the SigningMethod interface.
|
|
func (m *SigningMethodHMAC) Alg() string { return m.Name }
|
|
|
|
// Verify implements the Verify method from SigningMethod.
|
|
// For this signing method, must be a []byte.
|
|
func (m *SigningMethodHMAC) Verify(raw []byte, signature Signature, key interface{}) error {
|
|
keyBytes, ok := key.([]byte)
|
|
if !ok {
|
|
return ErrInvalidKey
|
|
}
|
|
hasher := hmac.New(m.Hash.New, keyBytes)
|
|
hasher.Write(raw)
|
|
if hmac.Equal(signature, hasher.Sum(nil)) {
|
|
return nil
|
|
}
|
|
return ErrSignatureInvalid
|
|
}
|
|
|
|
// Sign implements the Sign method from SigningMethod for this signing method.
|
|
// Key must be a []byte.
|
|
func (m *SigningMethodHMAC) Sign(data []byte, key interface{}) (Signature, error) {
|
|
keyBytes, ok := key.([]byte)
|
|
if !ok {
|
|
return nil, ErrInvalidKey
|
|
}
|
|
hasher := hmac.New(m.Hash.New, keyBytes)
|
|
hasher.Write(data)
|
|
return Signature(hasher.Sum(nil)), nil
|
|
}
|
|
|
|
// Hasher implements the SigningMethod interface.
|
|
func (m *SigningMethodHMAC) Hasher() crypto.Hash { return m.Hash }
|
|
|
|
// MarshalJSON implements json.Marshaler.
|
|
// See SigningMethodECDSA.MarshalJSON() for information.
|
|
func (m *SigningMethodHMAC) MarshalJSON() ([]byte, error) {
|
|
return []byte(`"` + m.Alg() + `"`), nil
|
|
}
|
|
|
|
var _ json.Marshaler = (*SigningMethodHMAC)(nil)
|