aboutsummaryrefslogblamecommitdiffstats
path: root/vendor/github.com/dgrijalva/jwt-go/hmac.go
blob: c22991925455606214c6ba6c567cb7794103de2b (plain) (tree)





























































































                                                                                            
package jwt

import (
    "crypto"
    "crypto/hmac"
    "errors"
)

// Implements the HMAC-SHA family of signing methods signing methods
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 "", ErrInvalidKey
}