Source file src/crypto/hmac/hmac.go

     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.
     4  
     5  /*
     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.
    10  
    11  Receivers should be careful to use Equal to compare MACs in order to avoid
    12  timing side-channels:
    13  
    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)
    17  		mac.Write(message)
    18  		expectedMAC := mac.Sum(nil)
    19  		return hmac.Equal(messageMAC, expectedMAC)
    20  	}
    21  */
    22  package hmac
    23  
    24  import (
    25  	"crypto/internal/boring"
    26  	"crypto/internal/fips/hmac"
    27  	"crypto/subtle"
    28  	"hash"
    29  )
    30  
    31  // New returns a new HMAC hash using the given [hash.Hash] type and key.
    32  // New functions like [crypto/sha256.New] can be used as h.
    33  // h must return a new Hash every time it is called.
    34  // Note that unlike other hash implementations in the standard library,
    35  // the returned Hash does not implement [encoding.BinaryMarshaler]
    36  // or [encoding.BinaryUnmarshaler].
    37  func New(h func() hash.Hash, key []byte) hash.Hash {
    38  	if boring.Enabled {
    39  		hm := boring.NewHMAC(h, key)
    40  		if hm != nil {
    41  			return hm
    42  		}
    43  		// BoringCrypto did not recognize h, so fall through to standard Go code.
    44  	}
    45  	return hmac.New(h, key)
    46  }
    47  
    48  // Equal compares two MACs for equality without leaking timing information.
    49  func Equal(mac1, mac2 []byte) bool {
    50  	// We don't have to be constant time if the lengths of the MACs are
    51  	// different as that suggests that a completely different hash function
    52  	// was used.
    53  	return subtle.ConstantTimeCompare(mac1, mac2) == 1
    54  }
    55  

View as plain text