mirror of
https://github.com/golang/go
synced 2024-11-25 23:58:02 -07:00
crypto/hmac: make Sum idempotent
Fixes #978. R=rsc CC=golang-dev https://golang.org/cl/1967045
This commit is contained in:
parent
33cb46903e
commit
ba5b09f786
@ -35,9 +35,8 @@ 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) }
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Repetive Sum() calls should return the same value
|
||||||
|
for k := 0; k < 2; k++ {
|
||||||
sum := fmt.Sprintf("%x", h.Sum())
|
sum := fmt.Sprintf("%x", h.Sum())
|
||||||
if sum != tt.out {
|
if sum != tt.out {
|
||||||
t.Errorf("test %d.%d: have %s want %s\n", i, j, 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.
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user