-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
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:
go/src/crypto/tls/key_schedule.go
Lines 38 to 40 in ca0e035
| 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:
Lines 14 to 20 in 594deca
| // 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).