crypto/rand: make Prime not deterministic for a fixed input stream

rand.Prime does not guarantee the precise prime selection algorithm as
part of its contract. For example, it changed slightly in CL 387554. We
want to ensure that no tests come to rely on it staying the same, so
just like other cryptographic functions that use randomness in an
unspecified way (ECDSA signing, RSA PKCS #1 v1.5 encryption, RSA key
generation), make it randomly read an extra byte or not.

Change-Id: Ib9079c03360812d412b7c21d5a06caadabb4a8bf
Reviewed-on: https://go-review.googlesource.com/c/go/+/391554
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
Filippo Valsorda 2022-03-10 11:43:43 -05:00 committed by Gopher Robot
parent 4aacb7ff0f
commit c18f398f32
3 changed files with 23 additions and 1 deletions

View File

@ -5,6 +5,7 @@
package rand
import (
"crypto/internal/randutil"
"errors"
"io"
"math/big"
@ -17,6 +18,8 @@ func Prime(rand io.Reader, bits int) (*big.Int, error) {
return nil, errors.New("crypto/rand: prime size must be at least 2-bit")
}
randutil.MaybeReadByte(rand)
b := uint(bits % 8)
if b == 0 {
b = 8

View File

@ -38,6 +38,25 @@ func TestPrimeBitsLt2(t *testing.T) {
}
}
func TestPrimeNondeterministic(t *testing.T) {
r := mathrand.New(mathrand.NewSource(42))
p0, err := rand.Prime(r, 32)
if err != nil {
t.Fatal(err)
}
for i := 0; i < 128; i++ {
r.Seed(42)
p, err := rand.Prime(r, 32)
if err != nil {
t.Fatal(err)
}
if p.Cmp(p0) != 0 {
return
}
}
t.Error("Prime always generated the same prime given the same input")
}
func TestInt(t *testing.T) {
// start at 128 so the case of (max.BitLen() % 8) == 0 is covered
for n := 128; n < 140; n++ {

View File

@ -416,8 +416,8 @@ var depsRules = `
# CRYPTO-MATH is core bignum-based crypto - no cgo, net; fmt now ok.
CRYPTO, FMT, math/big, embed
< crypto/rand
< crypto/internal/randutil
< crypto/rand
< crypto/ed25519
< encoding/asn1
< golang.org/x/crypto/cryptobyte/asn1