]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/rand: make Prime not deterministic for a fixed input stream
authorFilippo Valsorda <filippo@golang.org>
Thu, 10 Mar 2022 16:43:43 +0000 (11:43 -0500)
committerGopher Robot <gobot@golang.org>
Tue, 5 Apr 2022 01:35:39 +0000 (01:35 +0000)
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>
src/crypto/rand/util.go
src/crypto/rand/util_test.go
src/go/build/deps_test.go

index 0f143a3830203e119fcdfb17a4b343c636bf71be..11b1a28ec50f65109e04cecde7969ce78d10453a 100644 (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
index e76ce2018afe23edaa9af1f99bf4269c821cd0b5..9caf8e91ccf2abfcb65f9003cfc9c3632f246af0 100644 (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++ {
index c4fb2fe0b4e5bdb6a1a205478b01d0e727c96e97..052e7ad9c0d821975e18d4fddc1fe214cd301451 100644 (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