Copyright 2009 The Go Authors. All rights reserved. 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) asdefined 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 avoidtiming side-channels:
ValidMAC reports whether messageMAC is a valid HMAC tag for message. func ValidMAC(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 (
	
	
)
FIPS 198-1: https://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf
key is zero padded to the block size of the hash function ipad = 0x36 byte repeated for key length opad = 0x5c byte repeated for key length hmac = H([key ^ opad] H([key ^ ipad] text))
Marshalable is the combination of encoding.BinaryMarshaler and encoding.BinaryUnmarshaler. Their method definitions are repeated here to avoid a dependency on the encoding package.
type marshalable interface {
	MarshalBinary() ([]byte, error)
	UnmarshalBinary([]byte) error
}

type hmac struct {
	opad, ipad   []byte
	outer, inner hash.Hash
If marshaled is true, then opad and ipad do not contain a padded copy of the key, but rather the marshaled state of outer/inner after opad/ipad has been fed into it.
	marshaled bool
}

func ( *hmac) ( []byte) []byte {
	 := len()
	 = .inner.Sum()

	if .marshaled {
		if  := .outer.(marshalable).UnmarshalBinary(.opad);  != nil {
			panic()
		}
	} else {
		.outer.Reset()
		.outer.Write(.opad)
	}
	.outer.Write([:])
	return .outer.Sum([:])
}

func ( *hmac) ( []byte) ( int,  error) {
	return .inner.Write()
}

func ( *hmac) () int      { return .outer.Size() }
func ( *hmac) () int { return .inner.BlockSize() }

func ( *hmac) () {
	if .marshaled {
		if  := .inner.(marshalable).UnmarshalBinary(.ipad);  != nil {
			panic()
		}
		return
	}

	.inner.Reset()
	.inner.Write(.ipad)
If the underlying hash is marshalable, we can save some time by saving a copy of the hash state now, and restoring it on future calls to Reset and Sum instead of writing ipad/opad every time. If either hash is unmarshalable for whatever reason, it's safe to bail out here.
	,  := .inner.(marshalable)
	if ! {
		return
	}
	,  := .outer.(marshalable)
	if ! {
		return
	}

	,  := .MarshalBinary()
	if  != nil {
		return
	}

	.outer.Reset()
	.outer.Write(.opad)
	,  := .MarshalBinary()
	if  != nil {
		return
	}
Marshaling succeeded; save the marshaled state for later
	.ipad = 
	.opad = 
	.marshaled = true
}
New returns a new HMAC hash using the given hash.Hash type and key. New functions like sha256.New from crypto/sha256 can be used as h. h must return a new Hash every time it is called. Note that unlike other hash implementations in the standard library, the returned Hash does not implement encoding.BinaryMarshaler or encoding.BinaryUnmarshaler.
func ( func() hash.Hash,  []byte) hash.Hash {
	 := new(hmac)
	.outer = ()
	.inner = ()
	 := true
	func() {
The comparison might panic if the underlying types are not comparable.
			_ = recover()
		}()
		if .outer == .inner {
			 = false
		}
	}()
	if ! {
		panic("crypto/hmac: hash generation function does not produce unique values")
	}
	 := .inner.BlockSize()
	.ipad = make([]byte, )
	.opad = make([]byte, )
If key is too big, hash it.
		.outer.Write()
		 = .outer.Sum(nil)
	}
	copy(.ipad, )
	copy(.opad, )
	for  := range .ipad {
		.ipad[] ^= 0x36
	}
	for  := range .opad {
		.opad[] ^= 0x5c
	}
	.inner.Write(.ipad)

	return 
}
Equal compares two MACs for equality without leaking timing information.
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 subtle.ConstantTimeCompare(, ) == 1