From b2aa18b96cefb48641ec69a79bc67d030b93f093 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 7 Jan 2025 11:20:07 -0500 Subject: [PATCH] cmd/internal/hash: stop using md5, sha1 These break if the tools are run with GODEBUG=fips140=only, which happens if someone sets that during 'go test' (and a test binary must be built). The easiest fix is to make the tools compatible with this GODEBUG by just using sha256 as the underlying hash always. Just in case, I made the wrappers select different sections of the hash, but none of the call sites really care. This CL is for the Go 1.24 release, but a follow-up during the Go 1.25 dev cycle could change all the usage sites to only use Sum32/New32. For #70514 Fixes #70878 Change-Id: Id5fea779c83df51d1680dbe561e0949c56e8d1e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/641096 Reviewed-by: Keith Randall Auto-Submit: Russ Cox LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall --- src/cmd/internal/hash/hash.go | 41 +++++++++++++++++++++++---------- src/go/build/deps_test.go | 2 +- src/internal/pkgbits/encoder.go | 4 ++-- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/cmd/internal/hash/hash.go b/src/cmd/internal/hash/hash.go index 20edc72c20e648..a37368f50e74b9 100644 --- a/src/cmd/internal/hash/hash.go +++ b/src/cmd/internal/hash/hash.go @@ -5,22 +5,33 @@ // Package hash implements hash functions used in the compiler toolchain. package hash +// TODO(rsc): Delete the 16 and 20 forms and use 32 at all call sites. + import ( - "crypto/md5" - "crypto/sha1" "crypto/sha256" "hash" ) const ( - // Size32 is the size of 32 bytes hash checksum. - Size32 = sha256.Size - // Size20 is the size of 20 bytes hash checksum. - Size20 = sha1.Size - // Size16 is the size of 16 bytes hash checksum. - Size16 = md5.Size + // Size32 is the size of the 32-byte hash checksum. + Size32 = 32 + // Size20 is the size of the 20-byte hash checksum. + Size20 = 20 + // Size16 is the size of the 16-byte hash checksum. + Size16 = 16 ) +type shortHash struct { + hash.Hash + n int +} + +func (h *shortHash) Sum(b []byte) []byte { + old := b + sum := h.Hash.Sum(b) + return sum[:len(old)+h.n] +} + // New32 returns a new [hash.Hash] computing the 32 bytes hash checksum. func New32() hash.Hash { h := sha256.New() @@ -30,12 +41,12 @@ func New32() hash.Hash { // New20 returns a new [hash.Hash] computing the 20 bytes hash checksum. func New20() hash.Hash { - return sha1.New() + return &shortHash{New32(), 20} } // New16 returns a new [hash.Hash] computing the 16 bytes hash checksum. func New16() hash.Hash { - return md5.New() + return &shortHash{New32(), 16} } // Sum32 returns the 32 bytes checksum of the data. @@ -47,10 +58,16 @@ func Sum32(data []byte) [Size32]byte { // Sum20 returns the 20 bytes checksum of the data. func Sum20(data []byte) [Size20]byte { - return sha1.Sum(data) + sum := Sum32(data) + var short [Size20]byte + copy(short[:], sum[4:]) + return short } // Sum16 returns the 16 bytes checksum of the data. func Sum16(data []byte) [Size16]byte { - return md5.Sum(data) + sum := Sum32(data) + var short [Size16]byte + copy(short[:], sum[8:]) + return short } diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index d9d985dca4ade4..a62a5173b9c6bc 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -568,7 +568,7 @@ var depsRules = ` # crypto-aware packages - DEBUG, go/build, go/types, text/scanner, crypto/md5 + DEBUG, go/build, go/types, text/scanner, crypto/sha256 < internal/pkgbits, internal/exportdata < go/internal/gcimporter, go/internal/gccgoimporter, go/internal/srcimporter < go/importer; diff --git a/src/internal/pkgbits/encoder.go b/src/internal/pkgbits/encoder.go index c17a12399d0597..015842f58c06af 100644 --- a/src/internal/pkgbits/encoder.go +++ b/src/internal/pkgbits/encoder.go @@ -6,7 +6,7 @@ package pkgbits import ( "bytes" - "crypto/md5" + "crypto/sha256" "encoding/binary" "go/constant" "io" @@ -55,7 +55,7 @@ func NewPkgEncoder(version Version, syncFrames int) PkgEncoder { // DumpTo writes the package's encoded data to out0 and returns the // package fingerprint. func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) { - h := md5.New() + h := sha256.New() out := io.MultiWriter(out0, h) writeUint32 := func(x uint32) {