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.

hmac.go 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package jwt
  2. import (
  3. "crypto"
  4. "crypto/hmac"
  5. "errors"
  6. )
  7. // SigningMethodHMAC implements the HMAC-SHA family of signing methods.
  8. // Expects key type of []byte for both signing and validation
  9. type SigningMethodHMAC struct {
  10. Name string
  11. Hash crypto.Hash
  12. }
  13. // Specific instances for HS256 and company
  14. var (
  15. SigningMethodHS256 *SigningMethodHMAC
  16. SigningMethodHS384 *SigningMethodHMAC
  17. SigningMethodHS512 *SigningMethodHMAC
  18. ErrSignatureInvalid = errors.New("signature is invalid")
  19. )
  20. func init() {
  21. // HS256
  22. SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256}
  23. RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod {
  24. return SigningMethodHS256
  25. })
  26. // HS384
  27. SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384}
  28. RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod {
  29. return SigningMethodHS384
  30. })
  31. // HS512
  32. SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512}
  33. RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod {
  34. return SigningMethodHS512
  35. })
  36. }
  37. func (m *SigningMethodHMAC) Alg() string {
  38. return m.Name
  39. }
  40. // Verify implements token verification for the SigningMethod. Returns nil if
  41. // the signature is valid. Key must be []byte.
  42. //
  43. // Note it is not advised to provide a []byte which was converted from a 'human
  44. // readable' string using a subset of ASCII characters. To maximize entropy, you
  45. // should ideally be providing a []byte key which was produced from a
  46. // cryptographically random source, e.g. crypto/rand. Additional information
  47. // about this, and why we intentionally are not supporting string as a key can
  48. // be found on our usage guide
  49. // https://golang-jwt.github.io/jwt/usage/signing_methods/#signing-methods-and-key-types.
  50. func (m *SigningMethodHMAC) Verify(signingString string, sig []byte, key interface{}) error {
  51. // Verify the key is the right type
  52. keyBytes, ok := key.([]byte)
  53. if !ok {
  54. return newError("HMAC verify expects []byte", ErrInvalidKeyType)
  55. }
  56. // Can we use the specified hashing method?
  57. if !m.Hash.Available() {
  58. return ErrHashUnavailable
  59. }
  60. // This signing method is symmetric, so we validate the signature
  61. // by reproducing the signature from the signing string and key, then
  62. // comparing that against the provided signature.
  63. hasher := hmac.New(m.Hash.New, keyBytes)
  64. hasher.Write([]byte(signingString))
  65. if !hmac.Equal(sig, hasher.Sum(nil)) {
  66. return ErrSignatureInvalid
  67. }
  68. // No validation errors. Signature is good.
  69. return nil
  70. }
  71. // Sign implements token signing for the SigningMethod. Key must be []byte.
  72. //
  73. // Note it is not advised to provide a []byte which was converted from a 'human
  74. // readable' string using a subset of ASCII characters. To maximize entropy, you
  75. // should ideally be providing a []byte key which was produced from a
  76. // cryptographically random source, e.g. crypto/rand. Additional information
  77. // about this, and why we intentionally are not supporting string as a key can
  78. // be found on our usage guide https://golang-jwt.github.io/jwt/usage/signing_methods/.
  79. func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) ([]byte, error) {
  80. if keyBytes, ok := key.([]byte); ok {
  81. if !m.Hash.Available() {
  82. return nil, newError("HMAC sign expects []byte", ErrInvalidKeyType)
  83. }
  84. hasher := hmac.New(m.Hash.New, keyBytes)
  85. hasher.Write([]byte(signingString))
  86. return hasher.Sum(nil), nil
  87. }
  88. return nil, ErrInvalidKeyType
  89. }