1
2
3
4
5 package rand
6
7 import (
8 "crypto/internal/fips140only"
9 "crypto/internal/rand"
10 "errors"
11 "io"
12 "math/big"
13 )
14
15
16
17
18
19
20
21 func Prime(r io.Reader, bits int) (*big.Int, error) {
22 if fips140only.Enforced() {
23 return nil, errors.New("crypto/rand: use of Prime is not allowed in FIPS 140-only mode")
24 }
25 if bits < 2 {
26 return nil, errors.New("crypto/rand: prime size must be at least 2-bit")
27 }
28
29 r = rand.CustomReader(r)
30
31 b := uint(bits % 8)
32 if b == 0 {
33 b = 8
34 }
35
36 bytes := make([]byte, (bits+7)/8)
37 p := new(big.Int)
38
39 for {
40 if _, err := io.ReadFull(r, bytes); err != nil {
41 return nil, err
42 }
43
44
45 bytes[0] &= uint8(int(1<<b) - 1)
46
47
48
49
50 if b >= 2 {
51 bytes[0] |= 3 << (b - 2)
52 } else {
53
54 bytes[0] |= 1
55 if len(bytes) > 1 {
56 bytes[1] |= 0x80
57 }
58 }
59
60 bytes[len(bytes)-1] |= 1
61
62 p.SetBytes(bytes)
63 if p.ProbablyPrime(20) {
64 return p, nil
65 }
66 }
67 }
68
69
70
71 func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {
72 if max.Sign() <= 0 {
73 panic("crypto/rand: argument to Int is <= 0")
74 }
75 n = new(big.Int)
76 n.Sub(max, n.SetUint64(1))
77
78 bitLen := n.BitLen()
79 if bitLen == 0 {
80
81 return
82 }
83
84 k := (bitLen + 7) / 8
85
86 b := uint(bitLen % 8)
87 if b == 0 {
88 b = 8
89 }
90
91 bytes := make([]byte, k)
92
93 for {
94 _, err = io.ReadFull(rand, bytes)
95 if err != nil {
96 return nil, err
97 }
98
99
100
101 bytes[0] &= uint8(int(1<<b) - 1)
102
103 n.SetBytes(bytes)
104 if n.Cmp(max) < 0 {
105 return
106 }
107 }
108 }
109
View as plain text