GenerateDeterministicKey generates an RSA private key deterministically based on the provided seed. This function uses a deterministic random source to generate the primes p and q, ensuring that the same seed will always produce the same private key. The generated key is 2048 bits in size. Referenc
(seed int64)
| 12 | // |
| 13 | // Reference: https://pkg.go.dev/crypto/rsa#GenerateKey |
| 14 | func GenerateDeterministicKey(seed int64) *rsa.PrivateKey { |
| 15 | // Since the standard lib purposefully does not generate |
| 16 | // deterministic rsa keys, we need to do it ourselves. |
| 17 | |
| 18 | // Create deterministic random source |
| 19 | // nolint: gosec |
| 20 | deterministicRand := rand.New(rand.NewSource(seed)) |
| 21 | |
| 22 | // Use fixed values for p and q based on the seed |
| 23 | p := big.NewInt(0) |
| 24 | q := big.NewInt(0) |
| 25 | e := big.NewInt(65537) // Standard RSA public exponent |
| 26 | |
| 27 | for { |
| 28 | // Generate deterministic primes using the seeded random |
| 29 | // Each prime should be ~1024 bits to get a 2048-bit key |
| 30 | for { |
| 31 | p.SetBit(p, 1024, 1) // Ensure it's large enough |
| 32 | for i := range 1024 { |
| 33 | if deterministicRand.Int63()%2 == 1 { |
| 34 | p.SetBit(p, i, 1) |
| 35 | } else { |
| 36 | p.SetBit(p, i, 0) |
| 37 | } |
| 38 | } |
| 39 | p1 := new(big.Int).Sub(p, big.NewInt(1)) |
| 40 | if p.ProbablyPrime(20) && new(big.Int).GCD(nil, nil, e, p1).Cmp(big.NewInt(1)) == 0 { |
| 41 | break |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | for { |
| 46 | q.SetBit(q, 1024, 1) // Ensure it's large enough |
| 47 | for i := range 1024 { |
| 48 | if deterministicRand.Int63()%2 == 1 { |
| 49 | q.SetBit(q, i, 1) |
| 50 | } else { |
| 51 | q.SetBit(q, i, 0) |
| 52 | } |
| 53 | } |
| 54 | q1 := new(big.Int).Sub(q, big.NewInt(1)) |
| 55 | if q.ProbablyPrime(20) && p.Cmp(q) != 0 && new(big.Int).GCD(nil, nil, e, q1).Cmp(big.NewInt(1)) == 0 { |
| 56 | break |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | // Calculate phi = (p-1) * (q-1) |
| 61 | p1 := new(big.Int).Sub(p, big.NewInt(1)) |
| 62 | q1 := new(big.Int).Sub(q, big.NewInt(1)) |
| 63 | phi := new(big.Int).Mul(p1, q1) |
| 64 | |
| 65 | // Calculate private exponent d |
| 66 | d := new(big.Int).ModInverse(e, phi) |
| 67 | if d != nil { |
| 68 | // Calculate n = p * q |
| 69 | n := new(big.Int).Mul(p, q) |
| 70 | |
| 71 | // Create the private key |