-
+ D5A314BAA0F6D77B60210629541A02F8DD8923A03D0003A2005E46DCAC8022780577CF2D584BB869FD241A367153854838FBE88B46380914EDB6F35946B457DD
eucrypt/smg_rsa/primegen.c
(0 . 0)(1 . 105)
153 /* primegen.c - prime number generation and checks
154 *
155 * S.MG, 2017
156 *
157 */
158
159 #include <stdlib.h>
160 #include <unistd.h>
161 #include <assert.h>
162
163 #include "smg_rsa.h"
164
165 /****************
166 * is_composite
167 * Returns 1 if it finds evidence that n is composite and 0 otherwise.
168 * NB: this is a probabilistic test and its strength is directly linked to:
169 * - the number of witnesses AND
170 * - the quality of the entropy source given as arguments!
171 */
172
173 int is_composite( MPI n, int nwitnesses, int entropy_source) {
174 int evidence = 0;
175 int nlimbs = mpi_get_nlimbs(n); /* see MPI representation */
176 unsigned int nbits = mpi_get_nbits(n); /* used bits */
177 unsigned int noctets = (nbits + 7) / 8; /* source works on octets */
178
179 MPI nminus1 = mpi_alloc(nlimbs); /* n-1 value is used a LOT */
180 MPI mpi2 = mpi_alloc_set_ui(2); /* 2 as MPI */
181 MPI a = mpi_alloc(nlimbs); /* candidate witness */
182 MPI y = mpi_alloc(nlimbs); /* intermediate values */
183 MPI r = mpi_alloc(nlimbs); /* n = 1 + 2^s * r */
184 int s; /* n = 1 + 2^s * r */
185 int j; /* counter for loops */
186 int nread; /* number of random octets actually read */
187
188 /* precondition: n > 3 */
189 assert( nbits > 2 );
190
191 /* nminus1 = n - 1 as MPI */
192 mpi_sub_ui( nminus1, n, 1);
193
194 /*
195 * find r odd and s so that n = 1 + 2^s * r
196 * n-1 = 2^s * r
197 * s is given by the number of trailing zeros of binary n-1
198 * r is then obtained as (n-1) / (2^s)
199 */
200 s = mpi_trailing_zeros( nminus1 );
201 mpi_tdiv_q_2exp(r, nminus1, s);
202
203 /*
204 * Investigate randomly chosen candidate witnesses.
205 * Stop when either:
206 * the specified number of witnesses (nwitnesses) have
207 been investigated OR
208 * a witness for compositeness of n was found
209 */
210 while (nwitnesses > 0 && evidence == 0) {
211 unsigned char *p = xmalloc(noctets);
212 do {
213 nread = get_random_octets_from(noctets, p, entropy_source);
214 } while (nread != noctets);
215
216 mpi_set_buffer(a, p, noctets, 0);
217
218 /* ensure that a < n-1 by making a maximum nbits-1 long:
219 * clear all bits above nbits-2 in a
220 * keep value of bit nbits-2 in a as it was
221 */
222 if (mpi_test_bit(a, nbits - 2))
223 mpi_set_highbit(a, nbits - 2);
224 else
225 mpi_clear_highbit(a, nbits - 2);
226
227 /* ensure that 1 < a < n-1; if not, try another random number
228 * NB: true random means a CAN end up as 0 or 1 here.
229 */
230 if (mpi_cmp(a, nminus1) < 0 && mpi_cmp_ui(a, 1) > 0) {
231 /* calculate y = a^r mod n */
232 mpi_powm(y, a, r, n);
233 if (mpi_cmp_ui(y, 1) && mpi_cmp(y, nminus1)) {
234 j = 1;
235 while ( (j < s) && mpi_cmp(y, nminus1) && (evidence == 0) ) {
236 /* calculate y = y^2 mod n */
237 mpi_powm(y, y, mpi2, n);
238 if (mpi_cmp_ui(y, 1) == 0)
239 evidence = 1;
240 j = j + 1;
241 } /* end while */
242 if (mpi_cmp(y, nminus1))
243 evidence = 1;
244 } /* end if y != 1 and y != n-1 */
245 nwitnesses = nwitnesses - 1;
246 } /* end if 1 < a < n-1 */
247 xfree(p);
248 } /* end while for investigating candidate witnesses */
249
250 mpi_free( nminus1 );
251 mpi_free( mpi2 );
252 mpi_free( a );
253 mpi_free( y );
254 mpi_free( r );
255
256 return evidence;
257 }