1
0
mirror of https://github.com/golang/go synced 2024-11-22 07:44:43 -07:00

crypto/hmac: make Sum idempotent

Fixes #978.

R=rsc
CC=golang-dev
https://golang.org/cl/1967045
This commit is contained in:
Jukka-Pekka Kekkonen 2010-08-26 13:32:29 -04:00 committed by Russ Cox
parent 33cb46903e
commit ba5b09f786
5 changed files with 33 additions and 33 deletions

View File

@ -34,10 +34,9 @@ const (
) )
type hmac struct { type hmac struct {
size int size int
key []byte key, tmp []byte
tmp []byte outer, inner hash.Hash
inner hash.Hash
} }
func (h *hmac) tmpPad(xor byte) { func (h *hmac) tmpPad(xor byte) {
@ -50,14 +49,14 @@ func (h *hmac) tmpPad(xor byte) {
} }
func (h *hmac) Sum() []byte { func (h *hmac) Sum() []byte {
h.tmpPad(0x5c)
sum := h.inner.Sum() sum := h.inner.Sum()
h.tmpPad(0x5c)
for i, b := range sum { for i, b := range sum {
h.tmp[padSize+i] = b h.tmp[padSize+i] = b
} }
h.inner.Reset() h.outer.Reset()
h.inner.Write(h.tmp) h.outer.Write(h.tmp)
return h.inner.Sum() return h.outer.Sum()
} }
func (h *hmac) Write(p []byte) (n int, err os.Error) { func (h *hmac) Write(p []byte) (n int, err os.Error) {
@ -72,27 +71,26 @@ func (h *hmac) Reset() {
h.inner.Write(h.tmp[0:padSize]) h.inner.Write(h.tmp[0:padSize])
} }
// New returns a new HMAC hash using the given hash and key. // New returns a new HMAC hash using the given hash generator and key.
func New(h hash.Hash, key []byte) hash.Hash { func New(h func() hash.Hash, key []byte) hash.Hash {
hm := new(hmac)
hm.outer = h()
hm.inner = h()
hm.size = hm.inner.Size()
hm.tmp = make([]byte, padSize+hm.size)
if len(key) > padSize { if len(key) > padSize {
// If key is too big, hash it. // If key is too big, hash it.
h.Write(key) hm.outer.Write(key)
key = h.Sum() key = hm.outer.Sum()
} }
hm := new(hmac)
hm.inner = h
hm.size = h.Size()
hm.key = make([]byte, len(key)) hm.key = make([]byte, len(key))
for i, k := range key { copy(hm.key, key)
hm.key[i] = k
}
hm.tmp = make([]byte, padSize+hm.size)
hm.Reset() hm.Reset()
return hm return hm
} }
// NewMD5 returns a new HMAC-MD5 hash using the given key. // NewMD5 returns a new HMAC-MD5 hash using the given key.
func NewMD5(key []byte) hash.Hash { return New(md5.New(), key) } func NewMD5(key []byte) hash.Hash { return New(md5.New, key) }
// NewSHA1 returns a new HMAC-SHA1 hash using the given key. // NewSHA1 returns a new HMAC-SHA1 hash using the given key.
func NewSHA1(key []byte) hash.Hash { return New(sha1.New(), key) } func NewSHA1(key []byte) hash.Hash { return New(sha1.New, key) }

View File

@ -84,9 +84,13 @@ func TestHMAC(t *testing.T) {
t.Errorf("test %d.%d: Write(%d) = %d, %v", i, j, len(tt.in), n, err) t.Errorf("test %d.%d: Write(%d) = %d, %v", i, j, len(tt.in), n, err)
continue continue
} }
sum := fmt.Sprintf("%x", h.Sum())
if sum != tt.out { // Repetive Sum() calls should return the same value
t.Errorf("test %d.%d: have %s want %s\n", i, j, sum, tt.out) for k := 0; k < 2; k++ {
sum := fmt.Sprintf("%x", h.Sum())
if sum != tt.out {
t.Errorf("test %d.%d.%d: have %s want %s\n", i, j, k, sum, tt.out)
}
} }
// Second iteration: make sure reset works. // Second iteration: make sure reset works.

View File

@ -8,7 +8,6 @@ import (
"crypto/hmac" "crypto/hmac"
"crypto/rc4" "crypto/rc4"
"crypto/rsa" "crypto/rsa"
"crypto/sha1"
"crypto/subtle" "crypto/subtle"
"crypto/x509" "crypto/x509"
"io" "io"
@ -226,7 +225,7 @@ func (c *Conn) clientHandshake() os.Error {
cipher, _ := rc4.NewCipher(clientKey) cipher, _ := rc4.NewCipher(clientKey)
c.out.prepareCipherSpec(cipher, hmac.New(sha1.New(), clientMAC)) c.out.prepareCipherSpec(cipher, hmac.NewSHA1(clientMAC))
c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg) finished := new(finishedMsg)
@ -235,7 +234,7 @@ func (c *Conn) clientHandshake() os.Error {
c.writeRecord(recordTypeHandshake, finished.marshal()) c.writeRecord(recordTypeHandshake, finished.marshal())
cipher2, _ := rc4.NewCipher(serverKey) cipher2, _ := rc4.NewCipher(serverKey)
c.in.prepareCipherSpec(cipher2, hmac.New(sha1.New(), serverMAC)) c.in.prepareCipherSpec(cipher2, hmac.NewSHA1(serverMAC))
c.readRecord(recordTypeChangeCipherSpec) c.readRecord(recordTypeChangeCipherSpec)
if c.err != nil { if c.err != nil {
return c.err return c.err

View File

@ -16,7 +16,6 @@ import (
"crypto/hmac" "crypto/hmac"
"crypto/rc4" "crypto/rc4"
"crypto/rsa" "crypto/rsa"
"crypto/sha1"
"crypto/subtle" "crypto/subtle"
"crypto/x509" "crypto/x509"
"io" "io"
@ -227,7 +226,7 @@ func (c *Conn) serverHandshake() os.Error {
keysFromPreMasterSecret11(preMasterSecret, clientHello.random, hello.random, suite.hashLength, suite.cipherKeyLength) keysFromPreMasterSecret11(preMasterSecret, clientHello.random, hello.random, suite.hashLength, suite.cipherKeyLength)
cipher, _ := rc4.NewCipher(clientKey) cipher, _ := rc4.NewCipher(clientKey)
c.in.prepareCipherSpec(cipher, hmac.New(sha1.New(), clientMAC)) c.in.prepareCipherSpec(cipher, hmac.NewSHA1(clientMAC))
c.readRecord(recordTypeChangeCipherSpec) c.readRecord(recordTypeChangeCipherSpec)
if err := c.error(); err != nil { if err := c.error(); err != nil {
return err return err
@ -264,7 +263,7 @@ func (c *Conn) serverHandshake() os.Error {
finishedHash.Write(clientFinished.marshal()) finishedHash.Write(clientFinished.marshal())
cipher2, _ := rc4.NewCipher(serverKey) cipher2, _ := rc4.NewCipher(serverKey)
c.out.prepareCipherSpec(cipher2, hmac.New(sha1.New(), serverMAC)) c.out.prepareCipherSpec(cipher2, hmac.NewSHA1(serverMAC))
c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg) finished := new(finishedMsg)

View File

@ -20,7 +20,7 @@ func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
} }
// pHash implements the P_hash function, as defined in RFC 4346, section 5. // pHash implements the P_hash function, as defined in RFC 4346, section 5.
func pHash(result, secret, seed []byte, hash hash.Hash) { func pHash(result, secret, seed []byte, hash func() hash.Hash) {
h := hmac.New(hash, secret) h := hmac.New(hash, secret)
h.Write(seed) h.Write(seed)
a := h.Sum() a := h.Sum()
@ -46,8 +46,8 @@ func pHash(result, secret, seed []byte, hash hash.Hash) {
// pRF11 implements the TLS 1.1 pseudo-random function, as defined in RFC 4346, section 5. // pRF11 implements the TLS 1.1 pseudo-random function, as defined in RFC 4346, section 5.
func pRF11(result, secret, label, seed []byte) { func pRF11(result, secret, label, seed []byte) {
hashSHA1 := sha1.New() hashSHA1 := sha1.New
hashMD5 := md5.New() hashMD5 := md5.New
labelAndSeed := make([]byte, len(label)+len(seed)) labelAndSeed := make([]byte, len(label)+len(seed))
copy(labelAndSeed, label) copy(labelAndSeed, label)