1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
6 Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
7 defined in U.S. Federal Information Processing Standards Publication 198.
8 An HMAC is a cryptographic hash that uses a key to sign a message.
9 The receiver verifies the hash by recomputing it using the same key.
11 Receivers should be careful to use Equal to compare MACs in order to avoid
14 // ValidMAC reports whether messageMAC is a valid HMAC tag for message.
15 func ValidMAC(message, messageMAC, key []byte) bool {
16 mac := hmac.New(sha256.New, key)
18 expectedMAC := mac.Sum(nil)
19 return hmac.Equal(messageMAC, expectedMAC)
29 import "crypto/internal/boring"
32 // https://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf
34 // key is zero padded to the block size of the hash function
35 // ipad = 0x36 byte repeated for key length
36 // opad = 0x5c byte repeated for key length
37 // hmac = H([key ^ opad] H([key ^ ipad] text))
39 // Marshalable is the combination of encoding.BinaryMarshaler and
40 // encoding.BinaryUnmarshaler. Their method definitions are repeated here to
41 // avoid a dependency on the encoding package.
42 type marshalable interface {
43 MarshalBinary() ([]byte, error)
44 UnmarshalBinary([]byte) error
49 outer, inner hash.Hash
51 // If marshaled is true, then opad and ipad do not contain a padded
52 // copy of the key, but rather the marshaled state of outer/inner after
53 // opad/ipad has been fed into it.
57 func (h *hmac) Sum(in []byte) []byte {
62 if err := h.outer.(marshalable).UnmarshalBinary(h.opad); err != nil {
69 h.outer.Write(in[origLen:])
70 return h.outer.Sum(in[:origLen])
73 func (h *hmac) Write(p []byte) (n int, err error) {
74 return h.inner.Write(p)
77 func (h *hmac) Size() int { return h.outer.Size() }
78 func (h *hmac) BlockSize() int { return h.inner.BlockSize() }
80 func (h *hmac) Reset() {
82 if err := h.inner.(marshalable).UnmarshalBinary(h.ipad); err != nil {
91 // If the underlying hash is marshalable, we can save some time by
92 // saving a copy of the hash state now, and restoring it on future
93 // calls to Reset and Sum instead of writing ipad/opad every time.
95 // If either hash is unmarshalable for whatever reason,
96 // it's safe to bail out here.
97 marshalableInner, innerOK := h.inner.(marshalable)
101 marshalableOuter, outerOK := h.outer.(marshalable)
106 imarshal, err := marshalableInner.MarshalBinary()
112 h.outer.Write(h.opad)
113 omarshal, err := marshalableOuter.MarshalBinary()
118 // Marshaling succeeded; save the marshaled state for later
124 // New returns a new HMAC hash using the given hash.Hash type and key.
125 // Note that unlike other hash implementations in the standard library,
126 // the returned Hash does not implement encoding.BinaryMarshaler
127 // or encoding.BinaryUnmarshaler.
128 func New(h func() hash.Hash, key []byte) hash.Hash {
130 hm := boring.NewHMAC(h, key)
134 // BoringCrypto did not recognize h, so fall through to standard Go code.
139 blocksize := hm.inner.BlockSize()
140 hm.ipad = make([]byte, blocksize)
141 hm.opad = make([]byte, blocksize)
142 if len(key) > blocksize {
143 // If key is too big, hash it.
145 key = hm.outer.Sum(nil)
149 for i := range hm.ipad {
152 for i := range hm.opad {
155 hm.inner.Write(hm.ipad)
160 // Equal compares two MACs for equality without leaking timing information.
161 func Equal(mac1, mac2 []byte) bool {
162 // We don't have to be constant time if the lengths of the MACs are
163 // different as that suggests that a completely different hash function
165 return subtle.ConstantTimeCompare(mac1, mac2) == 1