...
1
2
3
4
5
22 package hmac
23
24 import (
25 "crypto/subtle"
26 "hash"
27 )
28
29
30
31
32
33
34
35
36
37
38
39
40 type marshalable interface {
41 MarshalBinary() ([]byte, error)
42 UnmarshalBinary([]byte) error
43 }
44
45 type hmac struct {
46 opad, ipad []byte
47 outer, inner hash.Hash
48
49
50
51
52 marshaled bool
53 }
54
55 func (h *hmac) Sum(in []byte) []byte {
56 origLen := len(in)
57 in = h.inner.Sum(in)
58
59 if h.marshaled {
60 if err := h.outer.(marshalable).UnmarshalBinary(h.opad); err != nil {
61 panic(err)
62 }
63 } else {
64 h.outer.Reset()
65 h.outer.Write(h.opad)
66 }
67 h.outer.Write(in[origLen:])
68 return h.outer.Sum(in[:origLen])
69 }
70
71 func (h *hmac) Write(p []byte) (n int, err error) {
72 return h.inner.Write(p)
73 }
74
75 func (h *hmac) Size() int { return h.outer.Size() }
76 func (h *hmac) BlockSize() int { return h.inner.BlockSize() }
77
78 func (h *hmac) Reset() {
79 if h.marshaled {
80 if err := h.inner.(marshalable).UnmarshalBinary(h.ipad); err != nil {
81 panic(err)
82 }
83 return
84 }
85
86 h.inner.Reset()
87 h.inner.Write(h.ipad)
88
89
90
91
92
93
94
95 marshalableInner, innerOK := h.inner.(marshalable)
96 if !innerOK {
97 return
98 }
99 marshalableOuter, outerOK := h.outer.(marshalable)
100 if !outerOK {
101 return
102 }
103
104 imarshal, err := marshalableInner.MarshalBinary()
105 if err != nil {
106 return
107 }
108
109 h.outer.Reset()
110 h.outer.Write(h.opad)
111 omarshal, err := marshalableOuter.MarshalBinary()
112 if err != nil {
113 return
114 }
115
116
117 h.ipad = imarshal
118 h.opad = omarshal
119 h.marshaled = true
120 }
121
122
123
124
125
126
127
128 func New(h func() hash.Hash, key []byte) hash.Hash {
129 hm := new(hmac)
130 hm.outer = h()
131 hm.inner = h()
132 unique := true
133 func() {
134 defer func() {
135
136 _ = recover()
137 }()
138 if hm.outer == hm.inner {
139 unique = false
140 }
141 }()
142 if !unique {
143 panic("crypto/hmac: hash generation function does not produce unique values")
144 }
145 blocksize := hm.inner.BlockSize()
146 hm.ipad = make([]byte, blocksize)
147 hm.opad = make([]byte, blocksize)
148 if len(key) > blocksize {
149
150 hm.outer.Write(key)
151 key = hm.outer.Sum(nil)
152 }
153 copy(hm.ipad, key)
154 copy(hm.opad, key)
155 for i := range hm.ipad {
156 hm.ipad[i] ^= 0x36
157 }
158 for i := range hm.opad {
159 hm.opad[i] ^= 0x5c
160 }
161 hm.inner.Write(hm.ipad)
162
163 return hm
164 }
165
166
167 func Equal(mac1, mac2 []byte) bool {
168
169
170
171 return subtle.ConstantTimeCompare(mac1, mac2) == 1
172 }
173
View as plain text