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