-
Notifications
You must be signed in to change notification settings - Fork 9
/
hmac.go
88 lines (73 loc) · 1.84 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
package tsig
import (
"crypto/hmac"
"crypto/md5" //nolint:gosec
"crypto/sha1" //nolint:gosec
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"encoding/hex"
"hash"
"github.com/miekg/dns"
)
// HMAC implements the standard HMAC TSIG methods using the dns.TsigProvider
// interface. It holds a map of TSIG key names to base64-encoded secrets. The
// key names should be in canonical form, see dns.CanonicalName.
type HMAC map[string]string
func fromBase64(s []byte) (buf []byte, err error) {
buflen := base64.StdEncoding.DecodedLen(len(s))
buf = make([]byte, buflen)
n, err := base64.StdEncoding.Decode(buf, s)
buf = buf[:n]
return
}
// Generate generates the TSIG MAC using the HMAC algorithm indicated by
// t.Algorithm using h[t.Hdr.Name] as the key.
// It returns the bytes for the TSIG MAC and any error that occurred.
func (h HMAC) Generate(msg []byte, t *dns.TSIG) ([]byte, error) {
var f func() hash.Hash
switch dns.CanonicalName(t.Algorithm) {
case dns.HmacMD5:
f = md5.New
case dns.HmacSHA1:
f = sha1.New
case dns.HmacSHA224:
f = sha256.New224
case dns.HmacSHA256:
f = sha256.New
case dns.HmacSHA384:
f = sha512.New384
case dns.HmacSHA512:
f = sha512.New
default:
return nil, dns.ErrKeyAlg
}
secret, ok := h[t.Hdr.Name]
if !ok {
return nil, dns.ErrSecret
}
rawsecret, err := fromBase64([]byte(secret))
if err != nil {
return nil, err
}
m := hmac.New(f, rawsecret)
m.Write(msg)
return m.Sum(nil), nil
}
// Verify verifies the TSIG MAC using the HMAC algorithm indicated by
// t.Algorithm using h[t.Hdr.Name] as the key.
// It returns any error that occurred.
func (h HMAC) Verify(msg []byte, t *dns.TSIG) error {
b, err := h.Generate(msg, t)
if err != nil {
return err
}
mac, err := hex.DecodeString(t.MAC)
if err != nil {
return err
}
if !hmac.Equal(b, mac) {
return dns.ErrSig
}
return nil
}