/* Random initialization for P-1 and P+1.
Copyright 2005 Paul Zimmermann and Alexander Kruppa.
This file is part of the ECM Library.
The ECM Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at your
option) any later version.
The ECM Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the ECM Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#ifdef OUTSIDE_LIBECM
# include "ecm-ecm.h"
#else
# include "ecm-impl.h"
#endif
#if HAVE_UNISTD_H
# include <unistd.h> /* getpid */
#endif
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#if defined (_MSC_VER) || defined (__MINGW32__)
# include <windows.h>
# include <wincrypt.h>
#endif
#if 0 /* dirty hack until outputf gets fixed */
#ifdef outputf
# undef outputf
# define outputf(x,y) printf(y)
#endif
#endif
/* put in 'a' a valid random seed for P-1, i.e. gcd(a,n)=1 and a <> {-1,1} */
void
pm1_random_seed (mpz_t a, mpz_t n, gmp_randstate_t randstate)
{
mpz_t q;
mpz_init (q);
do
{
mpz_urandomb (a, randstate, 32);
mpz_gcd (q, a, n);
}
while (mpz_cmp_ui (q, 1) != 0 || mpz_cmp_ui (a, 1) == 0 ||
mpz_cmp_si (a, -1) == 0);
mpz_clear (q);
}
/* put in seed a valid random seed for P+1 */
void
pp1_random_seed (mpz_t seed, mpz_t n, gmp_randstate_t randstate)
{
mpz_t q;
/* need gcd(p^2-4, n) = 1. */
mpz_init (q);
do
{
mpz_urandomb (q, randstate, 32);
mpz_add_ui (q, q, 1);
mpz_set (seed, q);
mpz_mul (q, q, q);
mpz_sub_ui (q, q, 4);
mpz_gcd (q, q, n);
}
while (mpz_cmp_ui (q, 1) != 0);
mpz_clear (q);
}
/* Produces a random unsigned int value */
#if defined (_MSC_VER) || defined (__MINGW32__)
unsigned int
get_random_ui (void)
{
SYSTEMTIME tv;
HCRYPTPROV Prov;
if (CryptAcquireContext (&Prov, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
int r;
unsigned int rnd;
r = CryptGenRandom (Prov, sizeof (unsigned int), (void *) &rnd);
CryptReleaseContext (Prov, 0);
if (r)
{
#ifndef OUTSIDE_LIBECM /* warning: outputf is not exported from libecm */
outputf (OUTPUT_DEVVERBOSE, "Got seed for RNG from CryptGenRandom\n");
#endif
return rnd;
}
}
#ifndef OUTSIDE_LIBECM /* warning: outputf is not exported from libecm */
outputf (OUTPUT_DEVVERBOSE, "Got seed for RNG from GetSystemTime\n");
#endif
GetSystemTime (&tv);
/* This gets us 27 bits of somewhat "random" data based on the time clock.
It would probably do the program justice if a better random mixing was done
in the non-MinGW get_random_ui if /dev/random does not exist */
return ((tv.wHour<<22)+(tv.wMinute<<16)+(tv.wSecond<<10)+tv.wMilliseconds) ^
((tv.wMilliseconds<<17)+(tv.wMinute<<11)+(tv.wHour<<6)+tv.wSecond);
}
#else
unsigned int
get_random_ui (void)
{
FILE *rndfd;
struct timeval tv;
unsigned int t;
/* Try /dev/urandom */
rndfd = fopen ("/dev/urandom", "r");
if (rndfd != NULL)
{
if (fread (&t, sizeof (unsigned int), 1, rndfd) == 1)
{
#ifndef OUTSIDE_LIBECM /* warning: outputf is not exported from libecm */
outputf (OUTPUT_DEVVERBOSE, "Got seed for RNG from /dev/urandom\n");
#endif
fclose (rndfd);
return t;
}
fclose (rndfd);
}
#if HAVE_GETTIMEOFDAY
if (gettimeofday (&tv, NULL) == 0)
{
#ifndef OUTSIDE_LIBECM
outputf (OUTPUT_DEVVERBOSE, "Got seed for RNG from gettimeofday()\n");
#endif
return tv.tv_sec + tv.tv_usec;
}
#endif
#ifndef OUTSIDE_LIBECM
outputf (OUTPUT_DEVVERBOSE, "Got seed for RNG from time()+getpid()\n");
#endif
/* Multiply one value by a large prime to get a bit of avalance effect */
return time (NULL) + getpid () * 2147483629;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1