type hmac struct {
size int
blocksize int
- key, tmp []byte
+ opad, ipad []byte
outer, inner hash.Hash
}
-func (h *hmac) tmpPad(xor byte) {
- for i, k := range h.key {
- h.tmp[i] = xor ^ k
- }
- for i := len(h.key); i < h.blocksize; i++ {
- h.tmp[i] = xor
- }
-}
-
func (h *hmac) Sum(in []byte) []byte {
origLen := len(in)
in = h.inner.Sum(in)
- h.tmpPad(0x5c)
- copy(h.tmp[h.blocksize:], in[origLen:])
h.outer.Reset()
- h.outer.Write(h.tmp)
+ h.outer.Write(h.opad)
+ h.outer.Write(in[origLen:])
return h.outer.Sum(in[:origLen])
}
func (h *hmac) Reset() {
h.inner.Reset()
- h.tmpPad(0x36)
- h.inner.Write(h.tmp[:h.blocksize])
+ h.inner.Write(h.ipad)
}
// New returns a new HMAC hash using the given hash.Hash type and key.
hm.inner = h()
hm.size = hm.inner.Size()
hm.blocksize = hm.inner.BlockSize()
- hm.tmp = make([]byte, hm.blocksize+hm.size)
+ hm.ipad = make([]byte, hm.blocksize)
+ hm.opad = make([]byte, hm.blocksize)
if len(key) > hm.blocksize {
// If key is too big, hash it.
hm.outer.Write(key)
key = hm.outer.Sum(nil)
}
- hm.key = make([]byte, len(key))
- copy(hm.key, key)
- hm.Reset()
+ copy(hm.ipad, key)
+ copy(hm.opad, key)
+ for i := range hm.ipad {
+ hm.ipad[i] ^= 0x36
+ }
+ for i := range hm.opad {
+ hm.opad[i] ^= 0x5c
+ }
+ hm.inner.Write(hm.ipad)
return hm
}
t.Error("Equal accepted unequal slices")
}
}
+
+func BenchmarkHMACSHA256_1K(b *testing.B) {
+ key := make([]byte, 32)
+ buf := make([]byte, 1024)
+ h := New(sha256.New, key)
+ b.SetBytes(int64(len(buf)))
+ for i := 0; i < b.N; i++ {
+ h.Write(buf)
+ h.Reset()
+ mac := h.Sum(nil)
+ buf[0] = mac[0]
+ }
+}
+
+func BenchmarkHMACSHA256_32(b *testing.B) {
+ key := make([]byte, 32)
+ buf := make([]byte, 32)
+ h := New(sha256.New, key)
+ b.SetBytes(int64(len(buf)))
+ for i := 0; i < b.N; i++ {
+ h.Write(buf)
+ h.Reset()
+ mac := h.Sum(nil)
+ buf[0] = mac[0]
+ }
+}