mirror of
https://github.com/golang/go
synced 2024-11-12 10:00:25 -07:00
crypto/hmac: add Equal function.
It was suggested that it's too easy to use crypto/hmac insecurely and I think that has some merit. This change adds a Equal function to make it obvious that MAC values should be compared in constant time. R=rsc, max CC=golang-dev https://golang.org/cl/6632044
This commit is contained in:
parent
4c473c02e1
commit
6720997f9e
@ -2,13 +2,27 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
|
||||
// defined in U.S. Federal Information Processing Standards Publication 198.
|
||||
// An HMAC is a cryptographic hash that uses a key to sign a message.
|
||||
// The receiver verifies the hash by recomputing it using the same key.
|
||||
/*
|
||||
Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
|
||||
defined in U.S. Federal Information Processing Standards Publication 198.
|
||||
An HMAC is a cryptographic hash that uses a key to sign a message.
|
||||
The receiver verifies the hash by recomputing it using the same key.
|
||||
|
||||
Receivers should be careful to use Equal to compare MACs in order to avoid
|
||||
timing side-channels:
|
||||
|
||||
// CheckMAC returns true if messageMAC is a valid HMAC tag for message.
|
||||
func CheckMAC(message, messageMAC, key []byte) bool {
|
||||
mac := hmac.New(sha256.New, key)
|
||||
mac.Write(message)
|
||||
expectedMAC := mac.Sum(nil)
|
||||
return hmac.Equal(messageMAC, expectedMAC)
|
||||
}
|
||||
*/
|
||||
package hmac
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"hash"
|
||||
)
|
||||
|
||||
@ -57,7 +71,7 @@ func (h *hmac) BlockSize() int { return h.blocksize }
|
||||
func (h *hmac) Reset() {
|
||||
h.inner.Reset()
|
||||
h.tmpPad(0x36)
|
||||
h.inner.Write(h.tmp[0:h.blocksize])
|
||||
h.inner.Write(h.tmp[:h.blocksize])
|
||||
}
|
||||
|
||||
// New returns a new HMAC hash using the given hash.Hash type and key.
|
||||
@ -78,3 +92,11 @@ func New(h func() hash.Hash, key []byte) hash.Hash {
|
||||
hm.Reset()
|
||||
return hm
|
||||
}
|
||||
|
||||
// Equal compares two MACs for equality without leaking timing information.
|
||||
func Equal(mac1, mac2 []byte) bool {
|
||||
// We don't have to be constant time if the lengths of the MACs are
|
||||
// different as that suggests that a completely different hash function
|
||||
// was used.
|
||||
return len(mac1) == len(mac2) && subtle.ConstantTimeCompare(mac1, mac2) == 1
|
||||
}
|
||||
|
@ -491,3 +491,22 @@ func TestHMAC(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
a := []byte("test")
|
||||
b := []byte("test1")
|
||||
c := []byte("test2")
|
||||
|
||||
if !Equal(b, b) {
|
||||
t.Error("Equal failed with equal arguments")
|
||||
}
|
||||
if Equal(a, b) {
|
||||
t.Error("Equal accepted a prefix of the second argument")
|
||||
}
|
||||
if Equal(b, a) {
|
||||
t.Error("Equal accepted a prefix of the first argument")
|
||||
}
|
||||
if Equal(b, c) {
|
||||
t.Error("Equal accepted unequal slices")
|
||||
}
|
||||
}
|
||||
|
@ -249,18 +249,23 @@ var pkgDeps = map[string][]string{
|
||||
"net/mail": {"L4", "NET", "OS"},
|
||||
"net/textproto": {"L4", "OS", "net"},
|
||||
|
||||
// Support libraries for crypto that aren't L2.
|
||||
"CRYPTO-SUPPORT": {
|
||||
"crypto/subtle",
|
||||
},
|
||||
|
||||
// Core crypto.
|
||||
"crypto/aes": {"L3"},
|
||||
"crypto/des": {"L3"},
|
||||
"crypto/hmac": {"L3"},
|
||||
"crypto/hmac": {"L3", "CRYPTO-SUPPORT"},
|
||||
"crypto/md5": {"L3"},
|
||||
"crypto/rc4": {"L3"},
|
||||
"crypto/sha1": {"L3"},
|
||||
"crypto/sha256": {"L3"},
|
||||
"crypto/sha512": {"L3"},
|
||||
"crypto/subtle": {"L3"},
|
||||
|
||||
"CRYPTO": {
|
||||
"CRYPTO-SUPPORT",
|
||||
"crypto/aes",
|
||||
"crypto/des",
|
||||
"crypto/hmac",
|
||||
@ -269,7 +274,6 @@ var pkgDeps = map[string][]string{
|
||||
"crypto/sha1",
|
||||
"crypto/sha256",
|
||||
"crypto/sha512",
|
||||
"crypto/subtle",
|
||||
},
|
||||
|
||||
// Random byte, number generation.
|
||||
|
Loading…
Reference in New Issue
Block a user