1
1
// CompactCryptoGroupAlgebra - C# implementation of abelian group algebra for experimental cryptography
2
2
3
- // SPDX-FileCopyrightText: 2022 Lukas Prediger <[email protected] >
3
+ // SPDX-FileCopyrightText: 2022-2024 Lukas Prediger <[email protected] >
4
4
// SPDX-License-Identifier: GPL-3.0-or-later
5
5
// SPDX-FileType: SOURCE
6
6
@@ -59,7 +59,7 @@ public static BigInteger GetBigIntegerBetween(
59
59
/// Returns a random positive <see cref="BigInteger"/> with the given bit length.
60
60
/// </summary>
61
61
/// <param name="randomNumberGenerator">Random number generator.</param>
62
- /// <param name="length">The bit length of the generator number.</param>
62
+ /// <param name="length">The bit length of the generated number.</param>
63
63
/// <returns>The random <see cref="BigInteger"/>.</returns>
64
64
public static BigInteger GetBigIntegerWithLength (
65
65
this RandomNumberGenerator randomNumberGenerator , NumberLength length
@@ -74,5 +74,40 @@ public static BigInteger GetBigIntegerWithLength(
74
74
candidate |= BigInteger . One << ( length . InBits - 1 ) ; // ensure msb is set to achieve desired length
75
75
return candidate ;
76
76
}
77
+
78
+ /// <summary>
79
+ /// Returns a random <see cref="BigPrime"/> with the given bit length.
80
+ /// </summary>
81
+ /// <param name="randomNumberGenerator">Random number generator.</param>
82
+ /// <param name="length">The bit length of the generated prime number.</param>
83
+ /// <returns>The random <see cref="BigPrime"/>.</returns>
84
+ public static BigPrime GetBigPrime (
85
+ this RandomNumberGenerator randomNumberGenerator , NumberLength length
86
+ )
87
+ {
88
+ BigInteger primeCandidate = randomNumberGenerator . GetBigIntegerWithLength ( length ) ;
89
+
90
+ // Ensure primeCandidate is odd.
91
+ primeCandidate |= 1 ;
92
+
93
+ // Ensure primeCandidate mod 6 == 1 or 5. Any prime p can only have p mod 6 == 1 or p mod 6 == 5.
94
+ // Relying on bit operations to avoid any branching statements.
95
+ var residue = primeCandidate % 6 ;
96
+ primeCandidate += residue & 2 ; // <-> primeCandidate += (residue == 3) ? 2 : 0;
97
+ residue += residue & 2 ; // <-> residue += (residue == 3) ? 2 : 0;
98
+ int step = 2 << ( int ) ( ( residue ^ ( residue >> 2 ) ) & 1 ) ; // <-> step = (residue == 1) ? 4 : 2;
99
+ int shiftDir = - 1 + ( step & 2 ) ; // <-> shiftDir = (step == 2) ? 1 : -1;
100
+
101
+ while ( ! PrimalityTest . IsProbablyPrime ( primeCandidate , randomNumberGenerator ) )
102
+ {
103
+ primeCandidate += step ;
104
+
105
+ // Below is equivalent to step = (step == 2) ? 4 : 2;
106
+ step = ( step << shiftDir ) | ( step >> - shiftDir ) ;
107
+ shiftDir = - shiftDir ;
108
+ }
109
+
110
+ return BigPrime . CreateWithoutChecks ( primeCandidate ) ;
111
+ }
77
112
}
78
113
}
0 commit comments