Commit 6a6a0734 authored by Dmitry Chestnykh's avatar Dmitry Chestnykh Committed by Adam Langley

crypto/hmac: simplify implementation

Store already padded keys instead of storing key and padding it during
Reset and Sum. This simplifies code and makes Reset-Write-Sum sequences
faster, which helps /x/crypto/pbkdf2.

HMAC benchmark:

benchmark                    old ns/op     new ns/op     delta
BenchmarkHMACSHA256_1K-4     7669          7613          -0.73%
BenchmarkHMACSHA256_32-4     1880          1737          -7.61%

benchmark                    old MB/s     new MB/s     speedup
BenchmarkHMACSHA256_1K-4     133.52       134.50       1.01x
BenchmarkHMACSHA256_32-4     17.02        18.41        1.08x

PBKDF2 benchmark:

benchmark                       old ns/op     new ns/op     delta
BenchmarkPBKDF2HMACSHA256-4     1943196       1807699       -6.97%

Change-Id: I6697028370c226715ab477b0844951a83eb3488c
Reviewed-on: https://go-review.googlesource.com/21024
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarAdam Langley <agl@golang.org>
parent 5c8674a4
......@@ -37,26 +37,16 @@ import (
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])
}
......@@ -70,8 +60,7 @@ func (h *hmac) BlockSize() int { return h.blocksize }
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.
......@@ -81,15 +70,22 @@ func New(h func() hash.Hash, key []byte) hash.Hash {
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
}
......
......@@ -568,3 +568,29 @@ func TestEqual(t *testing.T) {
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]
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment