/* * seedrandom - seed the cryptographically strong Blum generator * * Copyright (C) 1999 Landon Curt Noll * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc 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. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL. You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Under source code control: 1996/01/01 08:21:00 * File existed as early as: 1996 * * chongo /\oo/\ http://www.isthe.com/chongo/ * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ */ /* * The period of Blum generators with modulus 'n=p*q' (where p and * q are primes 3 mod 4) is: * * lambda(n) = lcm(factors of p-1 & q-1) * * One can construct a generator with a maximal period when * 'p' and 'q' have the fewest possible factors in common. * The quickest way to select such primes is only use 'p' * and 'q' when '(p-1)/2' and '(q-1)/2' are both primes. * This function will seed the random() generator that uses * such primes. * * given: * seed1 - a large random value (at least 10^20 and perhaps < 10^314) * seed2 - a large random value (at least 10^20 and perhaps < 10^314) * size - min Blum modulus as a power of 2 (at least 32, perhaps >= 512) * trials - number of ptest() trials (default 25) * * returns: * the previous random state * * NOTE: The [10^20, 10^314) range comes from the fact that the 13th internal * modulus is ~10^315. We want the lower bound seed to be reasonably big. */ define seedrandom(seed1, seed2, size, trials) { local p; /* first Blum prime */ local fp; /* prime co-factor of p-1 */ local sp; /* min bit size of p */ local q; /* second Blum prime */ local fq; /* prime co-factor of q-1 */ local sq; /* min bit size of q */ local n; /* Blum modulus */ local binsize; /* smallest power of 2 > n=p*q */ local r; /* initial quadratic residue */ local random_state; /* the initial rand state */ local random_junk; /* rand state that is not needed */ local old_state; /* old random state to return */ /* * firewall */ if (!isint(seed1)) { quit "1st arg (seed1) is not an int"; } if (!isint(seed2)) { quit "2nd arg (seed2) is not an int"; } if (!isint(size)) { quit "3rd arg (size) is not an int"; } if (!isint(trials)) { trials = 25; } if (digits(seed1) <= 20) { quit "1st arg (seed1) must be > 10^20 and perhaps < 10^314"; } if (digits(seed2) <= 20) { quit "2nd arg (seed2) must be > 10^20 and perhaps < 10^314"; } if (size < 32) { quit "3rd arg (size) needs to be >= 32 (perhaps >= 512)"; } if (trials < 1) { quit "4th arg (trials) must be > 0"; } /* * determine the search parameters */ ++size; /* convert power of 2 to bit length */ sp = int((size/2)-(size*0.03)+1); sq = size - sp; /* * find the first Blum prime */ random_state = srandom(seed1, 13); do { do { fp = nextcand(2^sp+randombit(sp), 1, 1, 3, 4); p = 2*fp+1; } while (ptest(p,1,0) == 0); } while(ptest(p, trials) == 0 || ptest(fp, trials) == 0); if (config("resource_debug") & 8) { print "/* 1st Blum prime */ p=", p; } /* * find the 2nd Blum prime */ random_junk = srandom(seed2, 13); do { do { fq = nextcand(2^sq+randombit(sq), 1, 1, 3, 4); q = 2*fq+1; } while (ptest(q,1,0) == 0); } while(ptest(q, trials) == 0 || ptest(fq, trials) == 0); if (config("resource_debug") & 8) { print "/* 2nd Blum prime */ q=", q; } /* * seed the Blum generator */ n = p*q; /* the Blum modulus */ binsize = highbit(n)+1; /* smallest power of 2 > p*q */ r = pmod(rand(1<