crypto/tls: deprecate Config.Rand

We now use SetGlobalRandom in recorded tests.

It was already partially ineffective: ML-KEM encapsulation, used as part
of X25519MLKEM768, doesn't take a source of randomness, and instead
always uses the global random source.

Fixes #79367

Change-Id: I1cc07ebec21bee32ece685efde188c0d6a6a6964
Reviewed-on: https://go-review.googlesource.com/c/go/+/765926
Auto-Submit: Filippo Valsorda <filippo@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Filippo Valsorda 2026-04-12 17:05:35 +02:00 committed by Gopher Robot
parent 542d7d549f
commit 27532dc35c
6 changed files with 31 additions and 43 deletions

1
api/next/79367.txt Normal file
View file

@ -0,0 +1 @@
pkg crypto/tls, type Config struct, Rand //deprecated #79367

View file

@ -0,0 +1,2 @@
[Config.Rand] is now deprecated.
For deterministic testing, use [testing/cryptotest.SetGlobalRandom].

View file

@ -572,10 +572,13 @@ const (
// modified. A Config may be reused; the tls package will also not
// modify it.
type Config struct {
// Rand provides the source of entropy for nonces and RSA blinding.
// Rand provides the source of entropy for the connection.
// If Rand is nil, TLS uses the cryptographic random reader in package
// crypto/rand.
// The Reader must be safe for use by multiple goroutines.
// crypto/rand. The Reader must be safe for use by multiple goroutines.
//
// Deprecated: this should be left nil in production. Not all TLS
// configurations are guaranteed to use Rand. Test code can use
// [testing/cryptotest.SetGlobalRandom] instead.
Rand io.Reader
// Time returns the current time as the number of seconds since the epoch.

View file

@ -14,14 +14,6 @@ import (
"time"
)
// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
type zeroSource struct{}
func (zeroSource) Read(b []byte) (n int, err error) {
clear(b)
return len(b), nil
}
func ExampleDial() {
// Connecting with a custom root-certificate set.
@ -70,19 +62,17 @@ TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
func ExampleConfig_keyLogWriter() {
// Debugging TLS applications by decrypting a network traffic capture.
// WARNING: Use of KeyLogWriter compromises security and should only be
// used for debugging.
// Dummy test HTTP server for the example with insecure random so output is
// reproducible.
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
server.TLS = &tls.Config{
Rand: zeroSource{}, // for example only; don't do this.
}
server := httptest.NewUnstartedServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {}))
server.StartTLS()
defer server.Close()
pool := x509.NewCertPool()
pool.AddCert(server.Certificate())
// Typically the log would go to an open file:
// w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
w := os.Stdout
@ -91,9 +81,7 @@ func ExampleConfig_keyLogWriter() {
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
KeyLogWriter: w,
Rand: zeroSource{}, // for reproducible output; don't do this.
InsecureSkipVerify: true, // test server certificate is not trusted.
RootCAs: pool,
},
},
}

View file

@ -1211,12 +1211,10 @@ func TestKeyLogTLS12(t *testing.T) {
clientConfig := testConfigClient.Clone()
clientConfig.KeyLogWriter = &clientBuf
clientConfig.MaxVersion = VersionTLS12
clientConfig.Rand = zeroSource{}
serverConfig := testConfigServer.Clone()
serverConfig.KeyLogWriter = &serverBuf
serverConfig.MaxVersion = VersionTLS12
serverConfig.Rand = zeroSource{}
c, s := localPipe(t)
done := make(chan bool)
@ -1242,17 +1240,23 @@ func TestKeyLogTLS12(t *testing.T) {
if len(loggedLine) == 0 {
t.Fatalf("%s: no keylog line was produced", side)
}
const expectedLen = 13 /* "CLIENT_RANDOM" */ +
1 /* space */ +
32*2 /* hex client nonce */ +
1 /* space */ +
48*2 /* hex master secret */ +
1 /* new line */
if len(loggedLine) != expectedLen {
t.Fatalf("%s: keylog line has incorrect length (want %d, got %d): %q", side, expectedLen, len(loggedLine), loggedLine)
rest, ok := strings.CutSuffix(loggedLine, "\n")
if !ok {
t.Fatalf("%s: keylog line is missing trailing newline: %q", side, loggedLine)
}
if !strings.HasPrefix(loggedLine, "CLIENT_RANDOM "+strings.Repeat("0", 64)+" ") {
t.Fatalf("%s: keylog line has incorrect structure or nonce: %q", side, loggedLine)
label, rest, ok := strings.Cut(rest, " ")
if !ok || label != "CLIENT_RANDOM" {
t.Fatalf("%s: keylog line has incorrect label: %q", side, loggedLine)
}
clientRandom, masterSecret, ok := strings.Cut(rest, " ")
if !ok {
t.Fatalf("%s: keylog line is missing master secret: %q", side, loggedLine)
}
if b, err := hex.DecodeString(clientRandom); err != nil || len(b) != 32 {
t.Fatalf("%s: keylog line has invalid client random: %q", side, loggedLine)
}
if b, err := hex.DecodeString(masterSecret); err != nil || len(b) != 48 {
t.Fatalf("%s: keylog line has invalid master secret: %q", side, loggedLine)
}
}
@ -1265,11 +1269,9 @@ func TestKeyLogTLS13(t *testing.T) {
clientConfig := testConfigClient.Clone()
clientConfig.KeyLogWriter = &clientBuf
clientConfig.Rand = zeroSource{}
serverConfig := testConfigServer.Clone()
serverConfig.KeyLogWriter = &serverBuf
serverConfig.Rand = zeroSource{}
c, s := localPipe(t)
done := make(chan bool)

View file

@ -394,14 +394,6 @@ Dialing:
panic("unreachable")
}
// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
type zeroSource struct{}
func (zeroSource) Read(b []byte) (n int, err error) {
clear(b)
return len(b), nil
}
func TestMain(m *testing.M) {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args)