-
Notifications
You must be signed in to change notification settings - Fork 1
/
hmac.go
92 lines (73 loc) · 2 KB
/
hmac.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
89
90
91
92
package jwt
import (
"crypto"
"crypto/hmac"
)
// SigningAlgorithmHMAC represents an HMAC signing algorithm
type SigningAlgorithmHMAC struct {
name string
hash crypto.Hash
}
// Instances of supported hashing algorithms
var (
HMAC = &SigningAlgorithmHMAC{"HS256", crypto.SHA256}
HS256 = &SigningAlgorithmHMAC{"HS256", crypto.SHA256}
HS384 = &SigningAlgorithmHMAC{"HS384", crypto.SHA384}
HS512 = &SigningAlgorithmHMAC{"HS512", crypto.SHA512}
)
// Name returns the name of the algorithm as specified in JSON Web Algorithms
func (alg *SigningAlgorithmHMAC) Name() string {
return alg.name
}
func (alg *SigningAlgorithmHMAC) sign(payload string, key interface{}) ([]byte, error) {
var byteArray []byte
switch k := key.(type) {
case []byte:
byteArray = k
case string:
byteArray = []byte(k)
default:
return nil, ErrInvalidKey
}
// byteArray now holds the key
// hmac.New expects a function to return the hash.Hash so we need to get a
// function to do that
hashFunc, err := newHashFunc(alg.hash)
if err != nil {
return nil, err
}
hasher := hmac.New(hashFunc, byteArray)
hasher.Write([]byte(payload))
return hasher.Sum(nil), nil
}
// Sign takes a string payload and either a byte array key or a string key and
// returns the signature as a string or an error
func (alg *SigningAlgorithmHMAC) Sign(payload string, key interface{}) (string, error) {
var (
sigBytes []byte
err error
)
if sigBytes, err = alg.sign(payload, key); err == nil {
return encode(sigBytes), nil
}
return "", err
}
// Verify calculates the signature and checks that it matches.
func (alg *SigningAlgorithmHMAC) Verify(payload string, signature string, key interface{}) error {
var (
checkSig []byte
origSig []byte
err error
)
if checkSig, err = alg.sign(payload, key); err != nil {
return err
}
if origSig, err = decode(signature); err != nil {
return err
}
// we have generated the signature, lets compare them
if hmac.Equal(checkSig, origSig) {
return nil
}
return ErrBadSignature
}