-
-
Notifications
You must be signed in to change notification settings - Fork 34
/
hmac_sha.go
88 lines (75 loc) · 2.05 KB
/
hmac_sha.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package jwt
import (
"crypto"
"crypto/hmac"
"hash"
"github.com/gbrlsnchs/jwt/v3/internal"
)
var (
// ErrHMACMissingKey is the error for trying to sign or verify a JWT with an empty key.
ErrHMACMissingKey = internal.NewError("jwt: HMAC key is empty")
// ErrHMACVerification is the error for an invalid signature.
ErrHMACVerification = internal.NewError("jwt: HMAC verification failed")
_ Algorithm = new(HMACSHA)
)
// HMACSHA is an algorithm that uses HMAC to sign SHA hashes.
type HMACSHA struct {
name string
key []byte
sha crypto.Hash
size int
pool *hashPool
}
func newHMACSHA(name string, key []byte, sha crypto.Hash) *HMACSHA {
if len(key) == 0 {
panic(ErrHMACMissingKey)
}
return &HMACSHA{
name: name, // cache name
key: key,
sha: sha,
size: sha.Size(), // cache size
pool: newHashPool(func() hash.Hash { return hmac.New(sha.New, key) }),
}
}
// NewHS256 creates a new algorithm using HMAC and SHA-256.
func NewHS256(key []byte) *HMACSHA {
return newHMACSHA("HS256", key, crypto.SHA256)
}
// NewHS384 creates a new algorithm using HMAC and SHA-384.
func NewHS384(key []byte) *HMACSHA {
return newHMACSHA("HS384", key, crypto.SHA384)
}
// NewHS512 creates a new algorithm using HMAC and SHA-512.
func NewHS512(key []byte) *HMACSHA {
return newHMACSHA("HS512", key, crypto.SHA512)
}
// Name returns the algorithm's name.
func (hs *HMACSHA) Name() string {
return hs.name
}
// Sign signs headerPayload using the HMAC-SHA algorithm.
func (hs *HMACSHA) Sign(headerPayload []byte) ([]byte, error) {
if string(hs.key) == "" {
return nil, ErrHMACMissingKey
}
return hs.pool.sign(headerPayload)
}
// Size returns the signature's byte size.
func (hs *HMACSHA) Size() int {
return hs.size
}
// Verify verifies a signature based on headerPayload using HMAC-SHA.
func (hs *HMACSHA) Verify(headerPayload, sig []byte) (err error) {
if sig, err = internal.DecodeToBytes(sig); err != nil {
return err
}
sig2, err := hs.Sign(headerPayload)
if err != nil {
return err
}
if !hmac.Equal(sig, sig2) {
return ErrHMACVerification
}
return nil
}