1
2
3
4
5
6
7 package cryptotest
8
9 import (
10 "bytes"
11 "crypto/ecdsa"
12 "crypto/elliptic"
13 "crypto/mlkem"
14 "crypto/rand"
15 "encoding/hex"
16 "testing"
17 )
18
19 func TestSetGlobalRandom(t *testing.T) {
20 seed1, _ := hex.DecodeString("6ae6783f4fbde91b6eb88b73a48ed247dbe5882e2579683432c1bfc525454add" +
21 "0cd87274d67084caaf0e0d36c8496db7fef55fe0e125750aa608d5e20ffc2d12")
22
23 t.Run("rand.Read", func(t *testing.T) {
24 buf := make([]byte, 64)
25
26 t.Run("seed 1", func(t *testing.T) {
27 SetGlobalRandom(t, 1)
28 rand.Read(buf)
29 if !bytes.Equal(buf, seed1) {
30 t.Errorf("rand.Read with seed 1 = %x; want %x", buf, seed1)
31 }
32
33 rand.Read(buf)
34 if bytes.Equal(buf, seed1) {
35 t.Errorf("rand.Read with seed 1 returned same output twice: %x", buf)
36 }
37
38 SetGlobalRandom(t, 1)
39 rand.Read(buf)
40 if !bytes.Equal(buf, seed1) {
41 t.Errorf("rand.Read with seed 1 after reset = %x; want %x", buf, seed1)
42 }
43
44 SetGlobalRandom(t, 1)
45 })
46
47 rand.Read(buf)
48 if bytes.Equal(buf, seed1) {
49 t.Errorf("rand.Read returned seeded output after test end")
50 }
51
52 t.Run("seed 2", func(t *testing.T) {
53 SetGlobalRandom(t, 2)
54 rand.Read(buf)
55 if bytes.Equal(buf, seed1) {
56 t.Errorf("rand.Read with seed 2 = %x; want different from %x", buf, seed1)
57 }
58 })
59 })
60
61 t.Run("rand.Reader", func(t *testing.T) {
62 buf := make([]byte, 64)
63
64 t.Run("seed 1", func(t *testing.T) {
65 SetGlobalRandom(t, 1)
66 rand.Reader.Read(buf)
67 if !bytes.Equal(buf, seed1) {
68 t.Errorf("rand.Reader.Read with seed 1 = %x; want %x", buf, seed1)
69 }
70
71 SetGlobalRandom(t, 1)
72 })
73
74 rand.Reader.Read(buf)
75 if bytes.Equal(buf, seed1) {
76 t.Errorf("rand.Reader.Read returned seeded output after test end")
77 }
78
79 oldReader := rand.Reader
80 t.Cleanup(func() { rand.Reader = oldReader })
81 rand.Reader = bytes.NewReader(bytes.Repeat([]byte{5}, 64))
82
83 t.Run("seed 1 again", func(t *testing.T) {
84 SetGlobalRandom(t, 1)
85 rand.Reader.Read(buf)
86 if !bytes.Equal(buf, seed1) {
87 t.Errorf("rand.Reader.Read with seed 1 = %x; want %x", buf, seed1)
88 }
89 })
90
91 rand.Reader.Read(buf)
92 if !bytes.Equal(buf, bytes.Repeat([]byte{5}, 64)) {
93 t.Errorf("rand.Reader not restored")
94 }
95 })
96
97
98 t.Run("mlkem.GenerateKey768", func(t *testing.T) {
99 exp, err := mlkem.NewDecapsulationKey768(seed1)
100 if err != nil {
101 t.Fatalf("mlkem.NewDecapsulationKey768: %v", err)
102 }
103
104 SetGlobalRandom(t, 1)
105 got, err := mlkem.GenerateKey768()
106 if err != nil {
107 t.Fatalf("mlkem.GenerateKey768: %v", err)
108 }
109
110 if gotBytes := got.Bytes(); !bytes.Equal(gotBytes, exp.Bytes()) {
111 t.Errorf("mlkem.GenerateKey768 with seed 1 = %x; want %x", gotBytes, exp.Bytes())
112 }
113 })
114
115
116 t.Run("ecdsa.GenerateKey", func(t *testing.T) {
117 exp, err := ecdsa.ParseRawPrivateKey(elliptic.P384(), seed1[:48])
118 if err != nil {
119 t.Fatalf("ecdsa.ParseRawPrivateKey: %v", err)
120 }
121
122 SetGlobalRandom(t, 1)
123 got, err := ecdsa.GenerateKey(elliptic.P384(), bytes.NewReader([]byte("this reader is ignored")))
124 if err != nil {
125 t.Fatalf("ecdsa.GenerateKey: %v", err)
126 }
127
128 if !got.Equal(exp) {
129 t.Errorf("ecdsa.GenerateKey with seed 1 = %x; want %x", got.D.Bytes(), exp.D.Bytes())
130 }
131 })
132
133
134
135 t.Run("cryptocustomrand=1", func(t *testing.T) {
136 t.Setenv("GODEBUG", "cryptocustomrand=1")
137
138 buf := make([]byte, 49)
139 buf[0] = 42
140 for i := 2; i < 49; i++ {
141 buf[i] = 1
142 }
143
144 exp1, err := ecdsa.ParseRawPrivateKey(elliptic.P384(), buf[:48])
145 if err != nil {
146 t.Fatalf("ecdsa.ParseRawPrivateKey: %v", err)
147 }
148 exp2, err := ecdsa.ParseRawPrivateKey(elliptic.P384(), buf[1:49])
149 if err != nil {
150 t.Fatalf("ecdsa.ParseRawPrivateKey: %v", err)
151 }
152
153 seen := [2]bool{}
154 for i := 0; i < 1000; i++ {
155 r := bytes.NewReader(buf)
156 got, err := ecdsa.GenerateKey(elliptic.P384(), r)
157 if err != nil {
158 t.Fatalf("ecdsa.GenerateKey: %v", err)
159 }
160 switch {
161 case got.Equal(exp1):
162 seen[0] = true
163 case got.Equal(exp2):
164 seen[1] = true
165 default:
166 t.Fatalf("ecdsa.GenerateKey with custom reader = %x; want %x or %x", got.D.Bytes(), exp1.D.Bytes(), exp2.D.Bytes())
167 }
168 if seen[0] && seen[1] {
169 break
170 }
171 }
172 if !seen[0] || !seen[1] {
173 t.Errorf("ecdsa.GenerateKey with custom reader did not produce both expected keys")
174 }
175
176
177 SetGlobalRandom(t, 1)
178
179 seen = [2]bool{}
180 for i := 0; i < 1000; i++ {
181 r := bytes.NewReader(buf)
182 got, err := ecdsa.GenerateKey(elliptic.P384(), r)
183 if err != nil {
184 t.Fatalf("ecdsa.GenerateKey: %v", err)
185 }
186 switch {
187 case got.Equal(exp1):
188 seen[0] = true
189 case got.Equal(exp2):
190 seen[1] = true
191 default:
192 t.Fatalf("ecdsa.GenerateKey with custom reader and SetGlobalRandom = %x; want %x or %x", got.D.Bytes(), exp1.D.Bytes(), exp2.D.Bytes())
193 }
194 if seen[0] && seen[1] {
195 break
196 }
197 }
198 if !seen[0] || !seen[1] {
199 t.Errorf("ecdsa.GenerateKey with custom reader and SetGlobalRandom did not produce both expected keys")
200 }
201 })
202 }
203
View as plain text