Skip to content

proposal: crypto/hmac: Sum function #75498

@tmthrgd

Description

@tmthrgd

Proposal Details

Many (perhaps most) uses of HMAC follow a very similar pattern:

h := hmac.New(somehash.New, key)
h.Write(data)
return h.Sum(nil)

For instance, in crypto/tls:

verifyData := hmac.New(c.hash.New, finishedKey)
verifyData.Write(transcript.Sum(nil))
return verifyData.Sum(nil)

There are also many other examples across GitHub: "hmac.New language:Go".

Even the package doc comment example:

// 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)
}

It would be nice if the standard library provided a convenience function to cover this common use case and reduce potential footguns.

package hmac

// Sum calculates the HMAC hash of message using the given [hash.Hash] type and key. New functions
// like [crypto/sha256.New] can be used as h.
func Sum[H hash.Hash](h func() H, key, message []byte) ([]byte, error)

I propose the signature be very similar to hkdf.Key, in particular taking a generic hash.Hash to allow for *sha3.SHA3, and other typed hashes, and returning an error. The error would allow the FIPS 140 related panics to instead be returned as errors.

#61477 contained discussion about whether the crypto/hkdf functions should return errors. Given that the error return only really exists for FIPS 140 and symmetry with hkdf.Key, it may be best to just leave the error off.

The likely implementation of this would just be a call to crypto/internal/fips140/hmac.New, Write and Sum, but in theory it could be optimised to be more performant at a later date. (Unless I'm mistaken, you can implemented Sum with a single hash instance rather than needing a separate one for inner and outer).

Metadata

Metadata

Assignees

No one assigned

    Labels

    ProposalProposal-CryptoProposal related to crypto packages or other security issues

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions