mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
1646 lines
55 KiB
Plaintext
1646 lines
55 KiB
Plaintext
/*
|
|
* cryrand - cryptographically strong pseudo-romandom number generator library
|
|
*/
|
|
/*
|
|
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and
|
|
* its documentation for any purpose and without fee is hereby granted,
|
|
* provided that the above copyright, this permission notice and text
|
|
* this comment, and the disclaimer below appear in all of the following:
|
|
*
|
|
* supporting documentation
|
|
* source copies
|
|
* source works derived from this source
|
|
* binaries derived from this source or from derived source
|
|
*
|
|
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
|
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
|
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* chongo was here /\../\
|
|
*/
|
|
|
|
/*
|
|
* XXX - Be sure that lambda(n) = lcm(factors of p-1 & q-1) is large
|
|
* for the default case.
|
|
*
|
|
* XXX - discuss lambda(n)
|
|
*
|
|
* XXX - In a future version of calc, these functions will become builtins.
|
|
* Some cleanup and simplification will also occur.
|
|
*/
|
|
|
|
/*
|
|
* These routines are written in the calc language. At the time of this
|
|
* notice, calc was at version 2.9.2 (We refer to calc, as in the C
|
|
* program, not the Emacs subsystem).
|
|
*
|
|
* Calc is available by anonymous ftp from ftp.uu.net under the
|
|
* directory /pub/calc.
|
|
*
|
|
* If you can't get calc any other way, EMail a request to my EMail
|
|
* address as shown below.
|
|
*
|
|
* Comments, suggestions, bug fixes and questions about these routines
|
|
* are welcome. Send EMail to the address given below.
|
|
*
|
|
* Happy bit twiddling,
|
|
*
|
|
* Landon Curt Noll
|
|
*
|
|
* chongo@toad.com
|
|
* ...!{pyramid,sun,uunet}!hoptoad!chongo
|
|
*/
|
|
|
|
/*
|
|
* AN OVERVIEW OF THE FUNCTIONS:
|
|
*
|
|
* This calc library contains a sample implementation of the crypto generator:
|
|
*
|
|
* cryrand - produce a cryptographically strong pseudo-random number
|
|
* scryrand - seed the crypto generator
|
|
* random - produce a cryptographically strong pseudo-random number
|
|
* over a given range
|
|
* srandom - seed random
|
|
*
|
|
* This generator is described in the papers:
|
|
*
|
|
* Blum, Blum, and Shub, "Comparison of Two Pseudorandom Number
|
|
* Generators", in Chaum, D. et. al., "Advances in Cryptology:
|
|
* Proceedings Crypto 82", pp. 61-79, Plenum Press, 1983.
|
|
*
|
|
* Blum, Blum, and Shub, "A Simple Unpredictable Pseudo-Random
|
|
* Number Generator", SIAM Journal of Computing, v. 15, n. 2,
|
|
* 1986, pp. 364-383.
|
|
*
|
|
* U. V. Vazirani and V. V. Vazirani, "Trapdoor Pseudo-Random
|
|
* Number Generators with Applications to Protocol Design",
|
|
* Proceedings of the 24th IEEE Symposium on the Foundations
|
|
* of Computer Science, 1983, pp. 23-30.
|
|
*
|
|
* U. V. Vazirani and V. V. Vazirani, "Efficient and Secure
|
|
* Pseudo-Random Number Generation", Proceedings of the 24th
|
|
* IEEE Symposium on the Foundations of Computer Science,
|
|
* 1984, pp. 458-463.
|
|
*
|
|
* U. V. Vazirani and V. V. Vazirani, "Efficient and Secure
|
|
* Pseudo-Random Number Generation", Advances in Cryptology -
|
|
* Proceedings of CRYPTO '84, Berlin: Springer-Verlag, 1985,
|
|
* pp. 193-202.
|
|
*
|
|
* "Probabilistic Encryption", Journal of Computer & System
|
|
* Sciences 28, pp. 270-299.
|
|
*
|
|
* We also refer to this generator as the 'Blum' generator.
|
|
*
|
|
* This generator is considered 'strong' in that it passes all
|
|
* polynomial-time statistical tests. The sequences produced
|
|
* are random in an absolutely precise way. There is absolutely
|
|
* no better way to predict the next bit in the sequence than by
|
|
* tossing a coin (as with TRULY random numbers) EVEN IF YOU KNOW
|
|
* THE MODULUS AND A LARGE PART OF THE PREVIOUSLY GENERATED BITS!
|
|
* An adversary would be far better advised to try to factor the
|
|
* modulus. And if we make the modulus hard to factor
|
|
* (such as the product of two large well chosen primes) this
|
|
* too can be made intractable for todays computers and methods.
|
|
*
|
|
* The crypto generator is not as fast as most generators, though
|
|
* it is not painfully slow either.
|
|
*
|
|
* One may fully seed this generator via scryrand(). Calling
|
|
* scryrand() with 1 or 3 arguments will result in the builtin
|
|
* rand() generator being seeded with the same seed. Calling
|
|
* scryrand() with 4 arguments, where the first argument
|
|
* is >= 0 will also result in the builtin rand() generator
|
|
* being seeded with the same seed.
|
|
*
|
|
* The random() generator is really another interface to the
|
|
* crypto generator. Unlike cryrand(), random() can return a
|
|
* value confined to either a half open (0 <= value < a) or closed
|
|
* interval (a <= value <= b). By default, a 64 bit value is
|
|
* returned.
|
|
*
|
|
* Calling srandom() simply calls scryrand(seed). The builtin
|
|
* rand() generator will be seeded with the same seed.
|
|
*
|
|
* The generator comes already seeded with precomputed initial constants.
|
|
* Thus, it is not required to seed a generator before using it.
|
|
*
|
|
* Using a seed of '0' will reload the generator with the initial state.
|
|
* In the case of scryrand(), lengths of -1 must also be supplied.
|
|
*
|
|
* scryrand(0,-1,-1) initializes all generators
|
|
* scryrand(0) initializes all generators
|
|
* srandom(0) initializes all generators
|
|
* randstate(0) initializes all generators
|
|
*
|
|
* All of the above single arg calls are fairly fast. In fact, passing
|
|
* seeding with a non-zero seed, in the above cases, where seed is
|
|
* not excessively large (many bits long), is also reasonably fast.
|
|
*
|
|
* The call:
|
|
*
|
|
* scryrand(-1, 0, in, ir)
|
|
*
|
|
* is fast because no checking is performed on the 'in', or 'ir'
|
|
* when seed is -1. NOTE: One must ensure that 'in' is the product of
|
|
* two Blum primes. To do this, one may use:
|
|
*
|
|
* nextcand(ip,cnt,0,3,4) * nextcand(ip+iq,cnt,0,3,4)
|
|
*
|
|
* where:
|
|
*
|
|
* ip is the initial search point for the 1st Blum prime
|
|
* iq is the initial search point for the 2nd Blum prime
|
|
* cnt is the pseudo test count (should be at least 1,
|
|
* this script uses 25)
|
|
*
|
|
* Note that the 4 arg call currently requires that the 2nd arg be 0.
|
|
* Non-zero 2nd arg values are reserved for future use.
|
|
*
|
|
* A call of scryrand(seed,len1,len2), with len1,len2 > 4, (3 args)
|
|
* is a somewhat slow as the length args increase. This type of
|
|
* call selects 2 primes that are used internally by the crypto
|
|
* generator. A call of scryrand(seed,ip,iq,ir) where seed >= 0
|
|
* is as slow as the 3 arg case. See scryrand() for more information.
|
|
*
|
|
* A call of scryrand() (no args) may be used to quickly change the
|
|
* internal state of the crypto and builtin rand() generators. Only one
|
|
* major internal crypto generator value (a quadratic residue) is randomly
|
|
* selected via the builtin rand() generator. The other 2 major internal
|
|
* values (the 2 Blum primes) are preserved. In this form, the builtin
|
|
* rand() generator is not seeded.
|
|
*
|
|
* Calling scryrand(seed,[len1,len2]) (1 or 3 args), or calling
|
|
* srandom(seed) will leave the builtin rand() generator in a
|
|
* seeded state as if the builtin srand(seed) has been called. Calling
|
|
* scryrand(seed,0,in,ir) (4 args), with seed>0 will also leave
|
|
* the builtin rand() generator in the same scryrand(seed) state.
|
|
*
|
|
* Calling scryrand() (no args) will not seed the builtin rand()
|
|
* generator before or afterwards. The builtin rand() generator
|
|
* will be changed as a side effect of that call.
|
|
*
|
|
* Calling srandom(seed) produces the same results as calling scryrand(seed).
|
|
*
|
|
* The state of the crypto generator is saved and restored via the
|
|
* randstate() function. Saving the state just after seeding a generator
|
|
* and restoring it later as a very fast way to reseed a generator.
|
|
*
|
|
* TRUTH IN ADVERTISING:
|
|
*
|
|
* Instead of searching for a Blum prime, we actually search for a
|
|
* probable prime. We use the word 'probable' because of an extremely
|
|
* extremely small chance that a composite (a non-prime) may be returned.
|
|
* We use the builtin function nextcand in its 5 arg form:
|
|
*
|
|
* nextcand(p, 25, 0, 3, 4)
|
|
*
|
|
* The odds that a number returned by the above call is not prime is
|
|
* less than 1 in 4^25. For our purposes, this is sufficient as the
|
|
* chance of returning a composite is much smaller than the chance that
|
|
* a hardware glitch will cause nextcand() to return a bogus result.
|
|
* In practive, the chance of the number returned by the above call is
|
|
* much much less than 1 in 4^25. The 1 in 4^n is a upper bound that
|
|
* has been shown to be much more pessimistic that observations suggest.
|
|
*
|
|
* Another "truth in advertising" issue is the use of the term
|
|
* 'pseudo-random'. All deterministic generators are pseudo random.
|
|
* This is opposed to true random generators based on some special
|
|
* physical device.
|
|
*
|
|
* The crypto generator is 'pseudo-random'. There is no statistical
|
|
* test, which runs in polynomial time, that can distinguish the crypto
|
|
* generator from a truly random source.
|
|
*
|
|
* A final "truth in advertising" issue deals with how the magic numbers
|
|
* found in this library were generated. Detains can be found in the
|
|
* various functions, while a overview can be found in the SOURCE FOR
|
|
* MAGIC NUMBERS section below.
|
|
*
|
|
****
|
|
*
|
|
* ON THE GENERATORS:
|
|
*
|
|
* The builtin rand() generator has a good period, and is fast. It is
|
|
* reasonable as generators go, though there are better ones available.
|
|
* We use it in seeding the crypto generator as its period and
|
|
* other statistical properties are good enough for our purposes.
|
|
*
|
|
* The crypto generator is the best generator in this package. It
|
|
* produces a cryptographically strong pseudo-random bit sequence.
|
|
* Internally, a fixed number of bits are generated after each
|
|
* generator iteration. Any unused bits are saved for the next call
|
|
* to the generator. The crypto generator is not too slow, though
|
|
* seeding the generator from scratch is slow. Shortcuts and
|
|
* pre-computer seeds have been provided for this reason. Use of
|
|
* crypto should be more than acceptable for many applications.
|
|
*
|
|
* The crypto seed is in 3 parts, the builtin rand() seed
|
|
* and two lengths. The two lengths specifies the minimum
|
|
* bit size of two primes used internal to the crypto generator.
|
|
* Not specifying the lengths, or using -1 will cause crypto to
|
|
* use the default minimum lengths of 504 and 541 bits, respectively.
|
|
*
|
|
* The random() function just another interface to the crypto
|
|
* generator. Like rand(), random() provides an interval capability
|
|
* (closed or open) as well as a 64 bit default return value.
|
|
* The random() function as good as crypto, and produces numbers
|
|
* that are equally cryptographically strong. One may use the
|
|
* seed functions srandom() or scryrand() for either the random()
|
|
* or cryrand() functions.
|
|
*
|
|
* The seed for the crypto generator may be of any size. Excessively
|
|
* large values of seed will result in increased memory usage as
|
|
* well as a larger seed time for the crypto generator.
|
|
* See REGARDING SEEDS below, for more information.
|
|
*
|
|
* One may save and restore the state of all generators via the
|
|
* randstate() function.
|
|
*
|
|
****
|
|
*
|
|
* REGARDING SEEDS:
|
|
*
|
|
* Because the generators are interrelated, seeding the crypto generator
|
|
* will directly or indirectly affect the builtin rand() generator.
|
|
* Seeding the crypto generator seeds the builtin rand() generator.
|
|
*
|
|
* The seed of '0' implies that a generator should be seeded back
|
|
* to its initial default state.
|
|
*
|
|
* For the moment, seeds < -1 are reserved for future use. The
|
|
* value of -1 is used as a special indicator to the fourth form
|
|
* of scryrand(), and it not a real seed.
|
|
*
|
|
* A seed may be of any size.
|
|
*
|
|
* There is no limit on the size of a seed. On the other hand,
|
|
* extremely large seeds require large tables and long seed times.
|
|
* Using a seed in the range of [2^64, 2^64 * 128!) should be
|
|
* sufficient for most purposes. An easy way to stay within this
|
|
* range to to use seeds that are between 21 and 215 digits, or 64 to
|
|
* 780 bits long.
|
|
*
|
|
****
|
|
*
|
|
* SOURCE OF MAGIC NUMBERS:
|
|
*
|
|
* Most of the magic constants used on this library ultimately are
|
|
* based on the Rand book of random numbers. The Rand book contains
|
|
* 10^6 decimal digits, generated by a physical process. This book,
|
|
* produced by the Rand corporation in the 1950's is considered
|
|
* a standard against which other generators may be measured.
|
|
*
|
|
* The Rand book of numbers was groups into groups of 20 digits.
|
|
* The first 55 groups < 2^64 were used to initialize add55_init_tbl.
|
|
* The size of 20 digits was used because 2^64 is 20 digits long.
|
|
* The restriction of < 2^64 was used to prevent modulus biasing.
|
|
*
|
|
* The additive 55 generator during seeding is used 128 times to help
|
|
* remove the initial seed state from the initial values produced.
|
|
* The loop count of 128 was a power of 2 that permits each of the
|
|
* 55 table entries to be processed at least twice.
|
|
*
|
|
* The quadratic residue search performed by cryres() starts at
|
|
* a value that is in the interval [2^sqrpow,n/2), where '2^sqrpow'
|
|
* is the smallest power of 2 >= 'n^(3/4)' where 'n=p*q'. We also
|
|
* reject any initial residue whose square (mod n) does not fit
|
|
* this same restriction. We reject any residue that is within
|
|
* 2^sqrpow of its square (mod n). Finally, we reject any quadratic
|
|
* residue or square mod n of a quadratic residue that is within
|
|
* 2^sqrpow of a simple fraction of n (n/k for some integer k).
|
|
*
|
|
* The use of 'n^(3/4)' insures that the quadratic residue is
|
|
* large, but not too large. We want to avoid residues that are
|
|
* near 0 or that are near 'n'. Such residues are trivial or
|
|
* semi-trivial. Applying the same restriction to the square
|
|
* of the initial residue avoid initial residues near 'sqrt(n)'.
|
|
* Such residues are trivial or semi-trivial as well.
|
|
*
|
|
* Avoiding residues whose squares (mod n) are not within 2^sqrpow of
|
|
* itself helps avoid selecting residue sequences (repeated
|
|
* squaring mod n) that initally do not change very much.
|
|
* Such residues might be somewhat trivial, so we play it safe.
|
|
*
|
|
* Taking some care to select a good initial residue helps
|
|
* eliminate cheep search attacks. It is true that a subsequent
|
|
* residue could be one of the residues that we would initially
|
|
* avoid. However such an occurance will happen after the
|
|
* generator is well underway and any such information
|
|
* has been lost.
|
|
*
|
|
* If we cannot find a good initial quadratic residue after
|
|
* 100 tries, we give up. The number '100' is somewhat arbitrary.
|
|
* For large 'n', a good quadratic residue is found after only
|
|
* a few tries. This value comes from the first 3 digits of the
|
|
* Rand book. Using a 4 digit count limit seemed excessive,
|
|
* and a 2 digit count (in this case 10) count be too small.
|
|
*
|
|
* Due to the initial quadratic residue selection process,
|
|
* the smallest of the larger Blum prime that is usable
|
|
* is 199. This is because 1393 = 7*199 is the smallest
|
|
* product of Blum primes that has a quadratic residue
|
|
* that is capable of passing the above restrictions.
|
|
*
|
|
* When searching for initial Blum primes, we do not know
|
|
* which initial search point will result in the larger
|
|
* Blum prime (due to possible random increments off of
|
|
* the search point). To be safe we will force both initial
|
|
* search points to be at lesast 199. This implies that the
|
|
* smallest usable n = p*q = 199*199 = 39601.
|
|
*
|
|
* Now since the lower bound for initial quadratic residues
|
|
* is '2^sqrpow', for the smallest n=39601 our lower bound
|
|
* is the value 2^12 or 4096. Thus we need not consider
|
|
* and initial starting quadratic value < 4096.
|
|
*
|
|
* The final magic numbers: '504' and '541' are the exponents the
|
|
* largest powers of 2 that are < the two default Blum primes 'p'
|
|
* and 'q' used by the crypto generator. The values of '504' and
|
|
* '541' implies that the product n=p*q > 2^1024. Each iteration
|
|
* of the crypto generator produces log2(log2(n=p*q)) random bits.
|
|
* The crypto generator is the most efficient when n is slightly >
|
|
* 2^(2^b). The product n > 2^(2^10)) produces 10 bits as efficiently
|
|
* as possible under the crypto generator process.
|
|
*
|
|
* Not being able to factor 'n=p*q' into 'p' and 'q' does not directly
|
|
* improve the quality crypto generator. On the other hand, it does
|
|
* improve the security of it.
|
|
*
|
|
* As we stated above, there is absolutely no better way to predict the
|
|
* sequence than by tossing a coin (as with TRULY random numbers) EVEN
|
|
* IF YOU KNOW THE MODULUS AND WHERE YOU ARE IN THE SEQUENCE! An
|
|
* adversary would be far better advised to try to factor the modulus
|
|
* and break the sequence that way. Thus we want to make 'n' hard
|
|
* to factor.
|
|
*
|
|
* The two len values differ slightly to avoid factorization attacks
|
|
* that work on numbers that are a perfect square, or where the two
|
|
* primes are nearly the same. I elected to have the sizes differ
|
|
* by 3% of the product size. The difference between '504' and
|
|
* '541', is '31', which is ~3.027% of '1024'. Now 3% of '1024' is
|
|
* '30.72', and the next largest whole number is '31'.
|
|
*
|
|
* The product n=p*q > 2^1024 implies a product if at least 309 digits.
|
|
* A product of two primes that is at least 309 digits is somewhat
|
|
* beyond Number Theory and computer power of Nov 1995, though this
|
|
* will likely change in the future.
|
|
*
|
|
* Again, the ability (or lack thereof) to factor 'n=p*q' does not
|
|
* directly relate to the strength of the crypto generator. We
|
|
* selected n=p*q > 2^1024 mainly because '1024 was a power of 2 and
|
|
* only slightly because it is up in the range where it is difficult
|
|
* to factor.
|
|
*
|
|
****
|
|
*
|
|
* FOR THE PARANOID:
|
|
*
|
|
* The truly paranoid might suggest that my claims in the MAGIC NUMBERS
|
|
* section are a lie intended to entrap people. Well they are not, but
|
|
* you need not take my word for it.
|
|
*
|
|
* The random numbers from the Rand book of random numbers can be
|
|
* verified by anyone who obtains the book. As these numbers were
|
|
* created before I (Landon Curt Noll) was born (you can look up
|
|
* my birth record if you want), I claim to have no possible influence
|
|
* on their generation.
|
|
*
|
|
* There is a very slight chance that the electronic copy of the
|
|
* Rand book that I was given access to differs from the printed text.
|
|
* I am willing to provide access to this electronic copy should
|
|
* anyone wants to compare it to the printed text.
|
|
*
|
|
* One could take issue with my selection of the default sizes '504'
|
|
* and '541'. As far as I know, 309 digits (1024 bits) is beyond the
|
|
* state of the art of Number Theory and Computation as of 17 Nov 95.
|
|
* It will likely be true that 309 digit products of two primes could
|
|
* come within reach in the next few years, but so what? If you are
|
|
* truly paranoid, why would you want to use the default seed, which
|
|
* is well known?
|
|
*
|
|
* The paranoid today might consider using the lengths of at least '504'
|
|
* and '541' will produce a product of two primes that is 202 digits.
|
|
* (the 2nd and 3rd args of scryrand > 504 & >541 respectively) Factoring
|
|
* 200+ digit product of two primes is well beyond the current hopes of
|
|
* Number Theory and Computer power, though even this limit may be passed
|
|
* someday.
|
|
*
|
|
* One might ask if value of '100' is too small with respect to the
|
|
* initial residue selection. Showing that '100' is too small would
|
|
* be difficult. Even if one could make that case, the chance that
|
|
* a 'problem' initial reside would be used would be very very small
|
|
* for non-trivial values of 'p' and 'q'.
|
|
*
|
|
* If all the above fails to pacify the truly paranoid, then one may
|
|
* select by some independent means, 2 Blum primes (primes mod 4 == 3,
|
|
* p < q), and a quadratic residue if p*q. Then by calling:
|
|
*
|
|
* scryrand(-1, 0, p*q, r)
|
|
*
|
|
* and then calling cryrand() or random(), one may bypass all magic
|
|
* numbers and use the pure generator.
|
|
*
|
|
* Note that randstate() may also be used by the truly paranoid.
|
|
* Even though it holds state for the other generators, their states
|
|
* are independent.
|
|
*
|
|
****
|
|
*
|
|
* GOALS:
|
|
*
|
|
* The goals of this package are:
|
|
*
|
|
* all magic numbers are explained
|
|
*
|
|
* I distrust systems with constants (magic numbers) and tables
|
|
* that have no justification (e.g., DES). I believe that I have
|
|
* done my best to justify all of the magic numbers used.
|
|
*
|
|
* full documentation
|
|
*
|
|
* You have this source file, plus background publications,
|
|
* what more could you ask?
|
|
*
|
|
* large selection of seeds
|
|
*
|
|
* Seeds are not limited to a small number of bits. A seed
|
|
* may be of any size.
|
|
*
|
|
* the strength of the generators may be tuned to meet the application need
|
|
*
|
|
* By using the appropriate seed arguments, one may increase
|
|
* the strength of the generator to suit the need of the
|
|
* application. One does not have just a few levels.
|
|
*
|
|
* This calc lib file is intended for demonstration purposes. Writing
|
|
* a C program (with possible assembly or libmp assist) would produce
|
|
* a faster generator.
|
|
*
|
|
* Even though I have done my best to implement a good system, you still
|
|
* must use these routines your own risk.
|
|
*
|
|
* Share and enjoy! :-)
|
|
*/
|
|
|
|
|
|
/*
|
|
* These constants are used by all of the generators in various direct and
|
|
* indirect forms.
|
|
*/
|
|
static cry_seed = 0; /* master seed */
|
|
|
|
|
|
/*
|
|
* cryobj - cryptographic pseudo-random state object
|
|
*/
|
|
obj cryobj { \
|
|
n, /* product of 2 Blum primes (prime 3 mod 4) */ \
|
|
r, /* quadratic residue of n=p*q */ \
|
|
exp, /* used in computing crypto good bits */ \
|
|
left, /* bits unused from the last cryrand() call */ \
|
|
bitcnt, /* left contains bitcnt crypto good bits */ \
|
|
seed /* last seed set by srand() or 0 */ \
|
|
}
|
|
|
|
|
|
/*
|
|
* initial cryptographic pseudo-random values - used by scryrand()
|
|
*
|
|
* These values are what the crypto generator is initialized with
|
|
* with this library first read. These values may be reproduced the
|
|
* hard way by calling scryrand(0,504,541) or scryrand(0,-1,-1).
|
|
*
|
|
* We will build up these values a piece at a time to avoid long lines
|
|
* that are difficult to send via EMail.
|
|
*
|
|
* NOTE: The primes that are used to compute the default value can
|
|
* be determined by examining this code. It is not intended that
|
|
* the default set of primes be hidden. If you want your product
|
|
* of two primes secret, then you need to seed the generator with
|
|
* an appropriate value. See the scryrand() function for details.
|
|
*/
|
|
/* product of 2 Blum primes (3 mod 4) */
|
|
static cryrand_init_n = 0x1657a14d00510c5f704ec;
|
|
cryrand_init_n <<= 200;
|
|
cryrand_init_n |= 0xaad832b9295595c981ab6aa0cde87b12be032ee74f4c0b4007;
|
|
cryrand_init_n <<= 200;
|
|
cryrand_init_n |= 0x24191787d27b72b7b1b340fce7cf1158456e43a2940306046c;
|
|
cryrand_init_n <<= 200;
|
|
cryrand_init_n |= 0x6720979d12905a39dd12693b2ab52c8be109b791f71e66b069;
|
|
cryrand_init_n <<= 200;
|
|
cryrand_init_n |= 0x25aa8cf167c21650fc92716802722852601f3dc30bb2c1374e;
|
|
cryrand_init_n <<= 200;
|
|
cryrand_init_n |= 0x8bbb19c47c2bd12e3e43b93ba20e6047c07e29a89a34991309;
|
|
/* value to use as a quadratic residue of n=p*q */
|
|
static cryrand_init_r = 0xc786ad03ebd254b3903f7e59d89b316d;
|
|
cryrand_init_r <<= 200;
|
|
cryrand_init_r |= 0x883ad980731281084d904323980830ec32ccb18af7faa070b7;
|
|
cryrand_init_r <<= 200;
|
|
cryrand_init_r |= 0x9a74dc95d0f61fc6ba3bc2599d952571bfb85081ffeec8995b;
|
|
|
|
/*
|
|
* cryptographic pseudo-random values - used by cryrand() and scryrand()
|
|
*/
|
|
/* n = p*q */
|
|
static cryrand_n = cryrand_init_n;
|
|
/* quad residue of n */
|
|
static cryrand_r = pmod(cryrand_init_r, 2, cryrand_init_n);
|
|
/* this cryrand() running exp used in computing crypto good bits */
|
|
static cryrand_exp = cryrand_r;
|
|
/* good crypto bits unused from the last cryrand() call */
|
|
static cryrand_left = 0;
|
|
/* the value cryrand_left contains cryrand_bitcnt crypto good bits */
|
|
static cryrand_bitcnt = 0;
|
|
|
|
|
|
/*
|
|
* cryrand - cryptographically strong pseudo-random number generator
|
|
*
|
|
* usage:
|
|
* cryrand(len)
|
|
*
|
|
* given:
|
|
* len number of pseudo-random bits to generate
|
|
*
|
|
* returns:
|
|
* a cryptographically strong pseudo-random number of len bits
|
|
*
|
|
* Internally, bits are produced log2(log2(n=p*q)) at a time. If a
|
|
* call to this function does not exhaust all of the collected bits,
|
|
* the unused bits will be saved away and used at a later call.
|
|
* Setting the seed via scryrand() or srandom() will clear out all
|
|
* unused bits. Thus:
|
|
*
|
|
* scryrand(0); <-- restore generator to initial state
|
|
* cryrand(16); <-- 16 bits
|
|
*
|
|
* will produce the same value as:
|
|
*
|
|
* scryrand(0); <-- restore generator to initial state
|
|
* cryrand(4)<<12 | cryrand(12); <-- 4+12 = 16 bits
|
|
*
|
|
* and will produce the same value as:
|
|
*
|
|
* scryrand(0); <-- restore generator to initial state
|
|
* cryrand(3)<<13 | cryrand(7)<<6 | cryrand(6); <-- 3+7+6 = 16 bits
|
|
*
|
|
* The crypto generator is not as fast as most generators, though it is not
|
|
* painfully slow either.
|
|
*
|
|
* NOTE: This function is the Blum cryptographically strong
|
|
* pseudo-random number generator.
|
|
*/
|
|
define
|
|
cryrand(len)
|
|
{
|
|
local goodbits; /* the number of good bits generated each pass */
|
|
local goodmask; /* mask for the low order good bits */
|
|
local randval; /* pseudo-random value being generated */
|
|
|
|
/*
|
|
* firewall
|
|
*/
|
|
if (!isint(len) || len < 1) {
|
|
quit "bad arg: len must be an integer > 0";
|
|
}
|
|
|
|
/*
|
|
* Determine how many bits may be generated each pass.
|
|
*
|
|
* The result by Alexi et. al., says that the log2(log2(n=p*q))
|
|
* least significant bits are secure, where log2(x) is log base 2.
|
|
*/
|
|
goodbits = highbit(highbit(cryrand_n));
|
|
goodmask = (1 << goodbits)-1;
|
|
|
|
/*
|
|
* If we have bits left over from the previous call, collect
|
|
* them now.
|
|
*/
|
|
if (cryrand_bitcnt > 0) {
|
|
|
|
/* case where the left over bits are enough for this call */
|
|
if (len <= cryrand_bitcnt) {
|
|
|
|
/* we need only len bits */
|
|
randval = (cryrand_left >> (cryrand_bitcnt-len));
|
|
|
|
/* save the unused bits for later use */
|
|
cryrand_left &= ((1 << (cryrand_bitcnt-len))-1);
|
|
|
|
/* save away the number of bits that we will not use */
|
|
cryrand_bitcnt -= len;
|
|
|
|
/* return our complete result */
|
|
return(randval);
|
|
|
|
/* case where we need more than just the left over bits */
|
|
} else {
|
|
|
|
/* clear out the number of left over bits */
|
|
len -= cryrand_bitcnt;
|
|
cryrand_bitcnt = 0;
|
|
|
|
/* collect all of the left over bits for now */
|
|
randval = cryrand_left;
|
|
}
|
|
|
|
/* case where we have no previously left over bits */
|
|
} else {
|
|
randval = 0;
|
|
}
|
|
|
|
/*
|
|
* Pump out len cryptographically strong pseudo-random bits,
|
|
* 'goodbits' at a time using Blum's process.
|
|
*/
|
|
while (len >= goodbits) {
|
|
|
|
/* generate the bits */
|
|
cryrand_exp = (cryrand_exp^2) % cryrand_n;
|
|
randval <<= goodbits;
|
|
randval |= (cryrand_exp & goodmask);
|
|
|
|
/* reduce the need count */
|
|
len -= goodbits;
|
|
}
|
|
|
|
/* if needed, save the unused bits for later use */
|
|
if (len > 0) {
|
|
|
|
/* generate the bits */
|
|
cryrand_exp = (cryrand_exp^2) % cryrand_n;
|
|
randval <<= len;
|
|
randval |= ((cryrand_exp&goodmask) >> (goodbits-len));
|
|
|
|
/* save away the number of bits that we will not use */
|
|
cryrand_left = cryrand_exp & ((1 << (goodbits-len))-1);
|
|
cryrand_bitcnt = goodbits-len;
|
|
}
|
|
|
|
/*
|
|
* return our pseudo-random bits
|
|
*/
|
|
return(randval);
|
|
}
|
|
|
|
|
|
/*
|
|
* scryrand - seed the cryptographically strong pseudo-random number generator
|
|
*
|
|
* usage:
|
|
* scryrand(seed)
|
|
* scryrand()
|
|
* scryrand(seed, len1, len2)
|
|
* scryrand(seed, 0, in, ir)
|
|
*
|
|
* input:
|
|
* [seed pseudo-random seed
|
|
* [len1 len2] minimum bit length of the Blum primes 'p' and 'q'
|
|
* -1 => default lengths
|
|
* [0 in ir] Initial values for Blum prime products 'p*q' and
|
|
* a quadratic residue 'r'
|
|
*
|
|
* returns:
|
|
* the previous seed
|
|
*
|
|
*
|
|
* This function will seed and setup the generator needed to produce
|
|
* cryptographically strong pseudo-random numbers.
|
|
*
|
|
* The first form of this function are fairly fast if the seed is not
|
|
* excessively large. The second form is also fairly fast if the internal
|
|
* primes are not too large. The third form, can take a long time to call.
|
|
* (see below) The fourth form, if the 'seed' arg is not -1, can take
|
|
* as long as the third form to call. If the fourth form is called with
|
|
* a 'seed' arg of -1, then it is fairly fast.
|
|
*
|
|
* Calling scryrand() with 1 or 3 args (first and third forms), or
|
|
* calling srandom(), or calling scryrand() with 4 args with the first
|
|
* arg >0, will leave the builtin rand() generator in a seeded state as if
|
|
* srand(seed) has been called.
|
|
*
|
|
* Calling scryrand() with no args will not seed the builtin rand()
|
|
* generator, before or afterwards, however the builtin rand() generator
|
|
* will have been changed as a side effect of that call.
|
|
*
|
|
* Calling scryrand() with 4 args where the first arg is 0 or '-1'
|
|
* will not change the other generators.
|
|
*
|
|
*
|
|
* First form of call: scryrand(seed)
|
|
*
|
|
* The first form of this function will seed the builtin rand() generator
|
|
* (via srand). The default precomputed constants will be used.
|
|
*
|
|
*
|
|
* Second form of call: scryrand()
|
|
*
|
|
* Only a new quadratic residue of n=p*q is recomputed. The previous prime
|
|
* values are kept.
|
|
*
|
|
* Unlike the first and second forms of this function, the builtin rand()
|
|
* generator function is not seeded before or after the call. The
|
|
* current state is used to generate a new quadratic residue of n=p*q.
|
|
*
|
|
*
|
|
* Third form of call: scryrand(seed, len1, len2)
|
|
*
|
|
* In the third form, 'len1' and 'len2' guide this function in selecting
|
|
* internally used prime numbers. The larger the lengths, the longer
|
|
* the time this function will take. The impact on execution time of
|
|
* cryrand() and random() may also be noticed, but not as much.
|
|
*
|
|
* If a length is '-1', then the default lengths (504 for len1, and 541
|
|
* for len2) are used. The call scryrand(0,-1,-1) recreates the initial
|
|
* crypto state the slow and hard way. (use scryrand(0) or srandom(0))
|
|
*
|
|
* This function can take a long time to call given reasonable values
|
|
* of len1 and len2. On an R4400, the time to seed was:
|
|
*
|
|
* Approx value digits seed time
|
|
* of len1+len2 in n=p*q in sec
|
|
* ------------ -------- ------
|
|
* 32 10 too small to measure
|
|
* 64 20 0.06
|
|
* 128 39 0.19
|
|
* 200 61 0.37
|
|
* 256 78 0.59
|
|
* 322 100 0.80
|
|
* 464 140 3.28
|
|
* 512 155 3.67
|
|
* 664 200 8.90
|
|
* 830 250 26.07
|
|
* 996 300 14.11 (Faster mult/square methods kick in
|
|
* 1024 309 40.44 in certain cases. Type help config
|
|
* 1328 400 158.52 in calc for more details.)
|
|
* 1586 478 96.54 (The time is also dependent on how
|
|
* 1660 500 296.84 many numbers we discard in during
|
|
* 2048 617 612.97 the search.)
|
|
*
|
|
* NOTE: The small lengths above are given for comparison
|
|
* purposes and are NOT recommended for actual use.
|
|
*
|
|
* NOTE: Generating crypto pseudo-random numbers is MUCH
|
|
* faster than seeding a crypto generator.
|
|
*
|
|
* NOTE: This calc lib file is intended for demonstration
|
|
* purposes. Writing a C program (with possible assembly
|
|
* or libmp assist) would produce a faster generator.
|
|
*
|
|
*
|
|
* Fourth form of call: scryrand(seed, 0, in, ir)
|
|
*
|
|
* In the fourth form, 'in' must be a product of two Blum primes.
|
|
* The arg 'ir' is the search point for the quadratic residue 'r'.
|
|
*
|
|
* As of this version, the 2nd arg of this 4 arg form must be 0.
|
|
* All other values are reserved for future use.
|
|
*
|
|
* WARNING: Pseudo prime checks are performed on the 'in' arg.
|
|
* Passing improper primes will likely produce poor results,
|
|
* or worse! A good way to ensure a quality 'in arg is
|
|
* to use the expression:
|
|
*
|
|
* nextcand(ip,cnt,0,3,4) * nextcand(ip+iq,cnt,0,3,4)
|
|
*
|
|
* where:
|
|
*
|
|
* ip is the initial search point for the 1st Blum prime
|
|
* iq is the initial search point for the 2nd Blum prime
|
|
* cnt is the pseudo test count (should be at least 1,
|
|
* this script uses 25)
|
|
*
|
|
* The 'seed' value is interpreted as follows:
|
|
*
|
|
* If seed > 0:
|
|
*
|
|
* Seed and use the builtin rand() generator to generate a search
|
|
* for a quadratic residue in the range '[0,ir)'.
|
|
*
|
|
* If seed == 0:
|
|
*
|
|
* Start searching for quadratic residue is 'ir'.
|
|
*
|
|
* This form does not change/seed the other generators.
|
|
*
|
|
* If seed == -1:
|
|
*
|
|
* Use 'ir' as the quadratic residue, do not search.
|
|
*
|
|
* This form does not change/seed the other generators.
|
|
*
|
|
*
|
|
* It should be noted that calling scryrand() while using the default
|
|
* primes took less than 0.01 seconds. Calling scryrand(0,-1,-1) took
|
|
* about 40 seconds.
|
|
*
|
|
* The paranoid, when giving explicit lengths, should keep in mind that
|
|
* len1 and len2 are the largest powers of 2 that are less than the two
|
|
* probable primes ('p' and 'q'). These two primes will be used
|
|
* internally to cryrand(). For simplicity, we refer to len1 and len2
|
|
* as bit lengths, even though they are actually 1 less then the
|
|
* minimum possible prime length.
|
|
*
|
|
* The actual lengths may exceed the lengths by slightly more than 3%.
|
|
* Furthermore, part of the strength of this generator rests on the
|
|
* difficultly to factor 'p*q'. Thus one should select 'len1' and 'len2'
|
|
* (from which 'p' and 'q' are selected) such that factoring a 'len1+len2'
|
|
* bit number is difficult.
|
|
*
|
|
* Not being able to factor 'n=p*q' into 'p' and 'q' does not directly
|
|
* improve the crypto generator. On the other hand, it can't hurt.
|
|
*
|
|
* There is no limit on the size of a seed. On the other hand,
|
|
* extremely large seeds require large tables and long seed times.
|
|
* Using a seed in the range of [2^64, 2^64 * 128!) should be
|
|
* sufficient for most purposes. An easy way to stay within this
|
|
* range to to use seeds that are between 21 and 215 digits long, or
|
|
* 64 to 780 bits long.
|
|
*
|
|
* NOTE: This function will clear any internally buffer bits. See
|
|
* cryrand() for details.
|
|
*
|
|
* NOTE: This function seeds the Blum cryptographically strong
|
|
* pseudo-random number generator.
|
|
*/
|
|
define
|
|
scryrand(seed,len1,len2,arg4)
|
|
{
|
|
local rval; /* a temporary pseudo-random value */
|
|
local oldseed; /* the previous seed */
|
|
local newres; /* the new quad res */
|
|
local in; /* Blum prime product */
|
|
local ir; /* initial quadratic residue search value */
|
|
local sqir; /* square of ir mod n */
|
|
local minres; /* minimum residue allowed */
|
|
local maxres; /* maximum residue allowed */
|
|
local cryrand_p; /* First Blum prime (3 mod 4) */
|
|
local cryrand_q; /* Second Blum prime (3 mod 4) */
|
|
|
|
/*
|
|
* firewall - avoid bogus args and very trivial lengths
|
|
*/
|
|
/* catch the case of no args - compute a different quadratic residue */
|
|
if (isnull(seed) && isnull(len1) && isnull(len2)) {
|
|
|
|
/* generate the next quadratic residue */
|
|
do {
|
|
newres = cryres(cryrand_n);
|
|
} while (newres == cryrand_r);
|
|
cryrand_r = newres;
|
|
cryrand_exp = cryrand_r;
|
|
|
|
/* clear the internal bits */
|
|
cryrand_left = 0;
|
|
cryrand_bitcnt = 0;
|
|
|
|
/* return the current seed early */
|
|
return (cry_seed);
|
|
}
|
|
if (!isint(seed)) {
|
|
quit "bad arg: seed arg (1st) must be an integer";
|
|
}
|
|
if (param(0) == 4) {
|
|
if (seed < -1) {
|
|
quit "bad arg: with 4 args: a seed < -1 is reserved for future use";
|
|
}
|
|
} else if (param(0) > 0 && seed < 0) {
|
|
quit "bad arg: a seed arg (1st) < 0 is reserved for future use";
|
|
}
|
|
|
|
/*
|
|
* 4 arg case: select or search for 'p', 'q' and 'r' from given values
|
|
*/
|
|
if (param(0) == 4) {
|
|
|
|
/* set initial values */
|
|
if (len1 != 0) {
|
|
quit "bad arg: 4 arg scryrand() call requires 2nd arg to be 0";
|
|
}
|
|
in = len2;
|
|
ir = arg4;
|
|
|
|
/*
|
|
* Unless prohibited by a seed of -1, force minimum values on
|
|
* 'in', and 'ir'.
|
|
*/
|
|
if (seed >= 0) {
|
|
/*
|
|
* Due to the initial quadratic residue selection process,
|
|
* the smallest of the larger Blum prime that is usable
|
|
* is 199. This is because 1393 = 7*199 is the smallest
|
|
* product of Blum primes that has a quadratic residue
|
|
* that is capable of passing thru cryres(). To be safe
|
|
* since we don't know which value (p or q) will end up
|
|
* being the larger Blum prime (due to the possible random
|
|
* increment below) we will force both initial search
|
|
* values to be at lesast 199.
|
|
*
|
|
* Now cryres() selects quadratic residues >= 2^sqrpow.
|
|
* '2^sqrpow' is the smallest power of 2 >= 'n^(3/4)' where
|
|
* 'n=p*q' is the product of two Blum primes. Since we
|
|
* force both Blum primes to be at least 199, the 2^sqrpow
|
|
* for the smallest n=199*199 is the value 2^12 or 4096.
|
|
* Thus we force the initial quadratic residue to be at
|
|
* least 4096.
|
|
*/
|
|
if (!isint(in) || in < 1393) {
|
|
in = 1393;
|
|
}
|
|
if (!isint(ir) || ir < 4096) {
|
|
ir = 4096;
|
|
}
|
|
}
|
|
/* remember our Blum prime product */
|
|
cryrand_n = in;
|
|
|
|
/*
|
|
* Determine our prime search points
|
|
*
|
|
* Unless we have a seed <= 0, we will add a random 64 bit
|
|
* value to the initial search points.
|
|
*/
|
|
if (seed > 0) {
|
|
/* add in a random value */
|
|
oldseed = srand(seed);
|
|
}
|
|
|
|
/*
|
|
* search for a quadratic residue
|
|
*/
|
|
if (seed >= 0) {
|
|
|
|
/*
|
|
* add in a random value to 'ir' if seeded
|
|
*
|
|
* Unless we have a seed <= 0, we will add a random 64 bit
|
|
* value to the initial search point.
|
|
*/
|
|
if (seed > 0) {
|
|
ir += rand();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We will reject any quadratic residue whose square mod n
|
|
* is outside of the [2^sqrpow,n-100] range, or whose square mod n
|
|
* is within 100 of itself.
|
|
*/
|
|
if (seed >= 0) {
|
|
minres = 2^(highbit(floor(power(cryrand_n,0.75)))+1);
|
|
maxres = cryrand_n - 100;
|
|
sqir = pmod(ir, 2, cryrand_n);
|
|
while (sqir < minres || sqir > maxres || abs(sqir-ir) <= 100) {
|
|
/* consdier the next residue since we don't like this one */
|
|
if (seed > 0) {
|
|
ir = sqir+rand()+1;
|
|
} else {
|
|
ir = sqir+1;
|
|
}
|
|
sqir = pmod(ir, 2, cryrand_n);
|
|
}
|
|
}
|
|
cryrand_r = pmod(ir, 2, cryrand_n);
|
|
|
|
/*
|
|
* clear the previously unused cryrand bits & other misc setup
|
|
*/
|
|
cryrand_left = 0;
|
|
cryrand_bitcnt = 0;
|
|
cryrand_exp = cryrand_r;
|
|
|
|
/*
|
|
* reseed the generator, if needed
|
|
*
|
|
* The crypto generator no longer needs the builtin rand()
|
|
* generator. We however, restore the builtin rand()
|
|
* generator back to its seeded state in order to be
|
|
* sure that it will be left in the same state.
|
|
*
|
|
* This will make more reproducible, calls to the builtin rand()
|
|
* generator; or more reproducible, calls to this function
|
|
* without args.
|
|
*/
|
|
if (seed > 0) {
|
|
ir = srand(seed); /* ignore this return value */
|
|
return(oldseed);
|
|
} else {
|
|
/* no seed change, return the current seed */
|
|
return (cry_seed);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If not the 4 arg case:
|
|
*
|
|
* convert explicit -1 args into default values
|
|
* convert missing args into -1 values (use precomputed tables)
|
|
*/
|
|
if ((isint(len1) && len1 != -1 && len1 < 5) ||
|
|
(isint(len2) && len2 != -1 && len2 < 5) ||
|
|
(!isint(len1) && isint(len2)) ||
|
|
(isint(len1) && !isint(len2))) {
|
|
quit "bad args: 2 & 3: if 2nd is given, must be -1 or ints > 4";
|
|
}
|
|
if (isint(len1) && len1 == -1) {
|
|
len1 = 504; /* default len1 value */
|
|
}
|
|
if (isint(len2) && len2 == -1) {
|
|
len2 = 541; /* default len2 value */
|
|
}
|
|
if (!isint(len1) && !isint(len2)) {
|
|
/* from here down, -1 means use precomputed values */
|
|
len1 = -1;
|
|
len2 = -1;
|
|
}
|
|
|
|
/*
|
|
* force len1 <= len2
|
|
*/
|
|
if (len1 > len2) {
|
|
swap(len1, len2);
|
|
}
|
|
|
|
/*
|
|
* seed the generator
|
|
*/
|
|
oldseed = srand(seed);
|
|
|
|
/*
|
|
* generate p and q Blum primes
|
|
*
|
|
* The Blum process requires the primes to be of the form 3 mod 4.
|
|
* We also generate n=p*q for future reference.
|
|
*
|
|
* We make sure that the lengths are the minimum lengths possible.
|
|
* We want some range to select a random prime from, so we
|
|
* go at least 3 bits higher, and as much as 3% plus 3 bits
|
|
* higher. Since the section is a random, how high really
|
|
* does not matter that much, but we want to avoid going to
|
|
* an extreme to keep the execution time from getting too long.
|
|
*
|
|
* Finally, we generate a quadratic residue of n=p*q.
|
|
*/
|
|
if (len1 > 0 && len2 > 0) {
|
|
/* generate a pseudo-random prime ~len1 bits long */
|
|
rval = rand(2^(len1-1), 2^((int(len1*1.03))+3));
|
|
cryrand_p = nextcand(rval,25,0,3,4);
|
|
|
|
/* generate a pseudo-random prime ~len2 bits long */
|
|
rval = rand(2^(len2-1), 2^((int(len2*1.03))+3));
|
|
cryrand_q = nextcand(rval,25,0,3,4);
|
|
|
|
/* here is our blum modulus */
|
|
cryrand_n = cryrand_p*cryrand_q;
|
|
cryrand_p = 0; /* clear value */
|
|
cryrand_q = 0; /* clear value */
|
|
|
|
} else {
|
|
|
|
/* use precomputed 'n' value */
|
|
cryrand_n = cryrand_init_n;
|
|
}
|
|
|
|
/*
|
|
* find the quadratic residue
|
|
*/
|
|
if (len1 == 504 && len2 == 541 && seed == 0) {
|
|
cryrand_r = cryrand_init_r;
|
|
} else {
|
|
cryrand_r = cryres(cryrand_n);
|
|
}
|
|
|
|
/*
|
|
* clear the previously unused cryrand bits & other misc setup
|
|
*/
|
|
cryrand_left = 0;
|
|
cryrand_bitcnt = 0;
|
|
|
|
/*
|
|
* ensure that r is a quadratic residue
|
|
*/
|
|
cryrand_r = pmod(cryrand_r, 2, cryrand_n);
|
|
cryrand_exp = cryrand_r;
|
|
|
|
/*
|
|
* reseed the generator
|
|
*
|
|
* The crypto generator no longer needs the builtin rand()
|
|
* generator. We however, restore the builtin rand() generator
|
|
* back to its seeded state in order to be sure that it
|
|
* will be left in the same state.
|
|
*/
|
|
/* we do not care about this old seed */
|
|
rval = srand(seed);
|
|
|
|
/*
|
|
* return the old seed
|
|
*/
|
|
return(oldseed);
|
|
}
|
|
|
|
|
|
/*
|
|
* random - a cryptographically strong pseudo-random number generator
|
|
*
|
|
* usage:
|
|
* random() - generate a pseudo-random integer >=0 and < 2^64
|
|
* random(a) - generate a pseudo-random integer >=0 and < a
|
|
* random(a,b) - generate a pseudo-random integer >=a and <= b
|
|
*
|
|
* returns:
|
|
* a large cryptographically strong pseudo-random number (see usage)
|
|
*
|
|
* This function is just another interface to the crypto generator.
|
|
* (see the cryrand() function).
|
|
*
|
|
* When no arguments are given, a pseudo-random number in the half open
|
|
* interval [0,2^64) is produced. This form is identical to calling
|
|
* cryrand(64).
|
|
*
|
|
* When 1 argument is given, a pseudo-random number in the half open interval
|
|
* [0,a) is produced.
|
|
*
|
|
* When 2 arguments are given, a pseudo-random number in the closed interval
|
|
* [a,b] is produced.
|
|
*
|
|
* This generator uses the crypto to return a large pseudo-random number.
|
|
*
|
|
* The input values a and b, if given, must be integers.
|
|
*
|
|
* Internally, bits are produced log2(log2(n=p*q)) at a time. If a
|
|
* call to this function does not exhaust all of the collected bits,
|
|
* the unused bits will be saved away and used at a later call.
|
|
* Setting the seed via scryrand(), srandom() or cryrand(len,1)
|
|
* will clear out all unused bits.
|
|
*
|
|
* NOTE: The BSD random() function returns only 31 bits, while we return 64.
|
|
*
|
|
* NOTE: This function is the Blum cryptographically strong
|
|
* pseudo-random number generator.
|
|
*/
|
|
define
|
|
random(a,b)
|
|
{
|
|
local range; /* we must generate [0,range) first */
|
|
local offset; /* what to add to get a adjusted range */
|
|
local rangebits; /* the number of bits in range */
|
|
local ret; /* pseudo-random bit value */
|
|
|
|
/*
|
|
* setup and special cases
|
|
*/
|
|
/* deal with the rand() case */
|
|
if (isnull(a) && isnull(b)) {
|
|
/* no args means return 64 bits */
|
|
return(cryrand(64));
|
|
}
|
|
/* firewall - args, if given must be in integers */
|
|
if (!isint(a) || (!isnull(b) && !isint(b))) {
|
|
quit "bad args: args, if given, must be integers";
|
|
}
|
|
/* convert random(x) into random(0,x-1) */
|
|
if (isnull(b)) {
|
|
/* convert call into a closed interval */
|
|
b = a-1;
|
|
a = 0;
|
|
/* firewall - random(0) should act like random(0,0) */
|
|
if (b == -1) {
|
|
return(0);
|
|
}
|
|
}
|
|
/* determine the range and offset */
|
|
if (a >= b) {
|
|
/* deal with the case of random(a,a) */
|
|
if (a == b) {
|
|
/* not very random, but it is true! */
|
|
return(a);
|
|
}
|
|
range = a-b+1;
|
|
offset = b;
|
|
} else {
|
|
/* convert random(a,b), where a<b, into random(b,a) */
|
|
range = b-a+1;
|
|
offset = a;
|
|
}
|
|
rangebits = highbit(range-1)+1;
|
|
/*
|
|
* At this point, we seek a pseudo-random number [0,range) to which
|
|
* we will add offset to produce a number [offset,range+offset).
|
|
*/
|
|
|
|
/*
|
|
* loop until we get a value that is in range
|
|
*
|
|
* We will obtain pseudo-random values over the range [0,2^rangebits)
|
|
* where 2^rangebits >= range and 2^(rangebits-1) < range. We
|
|
* will ignore any results that are > the range that we want.
|
|
*
|
|
* A note in modulus biasing:
|
|
*
|
|
* We will not fall into the trap of thinking that we can simply take
|
|
* a value mod 'range'. Consider the case where 'range' is '80'
|
|
* and we are given pseudo-random numbers [0,100). If we took them
|
|
* mod 80, then the numbers [0,20) would be produced more often
|
|
* because the numbers [81,100) mod 80 wrap back into [0,20).
|
|
*/
|
|
do {
|
|
/* obtain a pseudo-random value */
|
|
ret = cryrand(rangebits);
|
|
} while (ret >= range);
|
|
|
|
/*
|
|
* return the adjusted range value
|
|
*/
|
|
return(ret+offset);
|
|
}
|
|
|
|
|
|
/*
|
|
* srandom - seed the cryptographically strong pseudo-random number generator
|
|
*
|
|
* given:
|
|
* seed a random number seed
|
|
*
|
|
* returns:
|
|
* the previous seed
|
|
*
|
|
* This function is just another interface to the crypto generator.
|
|
* (see the scryrand() function).
|
|
*
|
|
* This function makes indirect use of the builtin rand() generator.
|
|
*
|
|
* There is no limit on the size of a seed. On the other hand,
|
|
* extremely large seeds require large tables and long seed times.
|
|
* Using a seed in the range of [2^64, 2^64 * 128!) should be
|
|
* sufficient for most purposes. An easy way to stay within this
|
|
* range to to use seeds that are between 21 and 215 digits long, or
|
|
* 64 to 780 bits long.
|
|
*
|
|
* NOTE: Calling this function will clear any internally buffer bits.
|
|
* See cryrand() for details.
|
|
*
|
|
* NOTE: This function seeds the Blum cryptographically strong
|
|
* pseudo-random number generator.
|
|
*/
|
|
define
|
|
srandom(seed)
|
|
{
|
|
if (!isint(seed)) {
|
|
quit "bad arg: seed must be an integer";
|
|
}
|
|
if (seed < 0) {
|
|
quit "bad arg: seed < 0 is reserved for future use";
|
|
}
|
|
return(scryrand(seed));
|
|
}
|
|
|
|
|
|
/*
|
|
* randstate - set/get the state of all of the generators
|
|
*
|
|
* usage:
|
|
* randstate() return the current state
|
|
* randstate(0) return the previous state, set the default state
|
|
* randstate(cobj) return the previous state, set a new state
|
|
*
|
|
* In the first form: randstate()
|
|
*
|
|
* This function returns an cryobj object containing information
|
|
* about the current state of all of the generators.
|
|
*
|
|
* In the second form: randstate(0)
|
|
*
|
|
* This function sets all of the generators to the default initial
|
|
* state (i.e., the state when this library was loaded).
|
|
*
|
|
* This function returns an cryobj object containing information
|
|
* about the previous state of all of the generators.
|
|
*
|
|
* In the third form: randstate(cobj)
|
|
*
|
|
* This function sets all of the generators to the state as found
|
|
* in the cryobj object.
|
|
*
|
|
* This function returns an cryobj object containing information
|
|
* about the previous state of all of the generators.
|
|
*
|
|
* This function may be used to save and restore cryrand() & random()
|
|
* generator states. For example:
|
|
*
|
|
* state = randstate() <-- save the current state
|
|
* random() <-- print the next 64 bits
|
|
* randstate(state) <-- restore previous state
|
|
* random() <-- print the same 64 bits
|
|
*
|
|
* One may quickly reseed a generator. For example:
|
|
*
|
|
* srandom(1,330,350) <-- seed the generator
|
|
* seed1state = randstate() <-- remember this 1st seeded state
|
|
* random() <-- print 1st 64 bits seed 1 generator
|
|
* srandom(2,331,351) <-- seed the generator again
|
|
* seed2state = randstate() <-- remember this 2nd seeded state
|
|
* random() <-- print 1st 64 bits seed 2 generator
|
|
*
|
|
* randstate(seed1state) <-- reseed to the 1st seeded state
|
|
* random() <-- reprint 1st 64 bits seed 1 generator
|
|
* randstate(seed2state) <-- reseed to the 2nd seeded state
|
|
* random() <-- reprint 1st 64 bits seed 2 generator
|
|
*
|
|
* given:
|
|
* cobj if a cryobj object, use that object to set the current state
|
|
* if 0, set to the default state
|
|
*
|
|
* return:
|
|
* return the state of the crypto pseudo-random number generator in
|
|
* the form of an cryobj object, as it was prior to this call
|
|
*
|
|
* NOTE: No checking is performed on the data the 3rd form (cryobj object
|
|
* arg) is used. The user must ensure that the arg represents a valid
|
|
* generator state.
|
|
*
|
|
* NOTE: When using the second form (passing an integer arg), only 0 is
|
|
* defined. All other integer values are reserved for future use.
|
|
*/
|
|
define
|
|
randstate(arg)
|
|
{
|
|
/* declare our objects */
|
|
local obj cryobj x; /* firewall comparator */
|
|
local obj cryobj prev; /* previous states of the generators */
|
|
local junk; /* dummy holder of random values */
|
|
|
|
/* firewall */
|
|
if (!isint(arg) && !istype(arg,x) && !isnull(arg)) {
|
|
quit "bad arg: argument must be integer, an cryobj object or missing";
|
|
}
|
|
if (isint(arg) && arg != 0) {
|
|
quit "bad arg: non-zero integer arguments are reserved for future use";
|
|
}
|
|
|
|
/*
|
|
* save the current state
|
|
*/
|
|
prev.n = cryrand_n;
|
|
prev.r = cryrand_r;
|
|
prev.exp = cryrand_exp;
|
|
prev.left = cryrand_left;
|
|
prev.bitcnt = cryrand_bitcnt;
|
|
prev.seed = cry_seed;
|
|
if (isnull(x)) {
|
|
/* if no args, just return current state */
|
|
return (prev);
|
|
}
|
|
|
|
/*
|
|
* deal with the cryobj arg - set the state
|
|
*/
|
|
if (istype(arg, x)) {
|
|
/* set the state from this object */
|
|
cryrand_n = cryrand_n;
|
|
cryrand_r = arg.r;
|
|
cryrand_exp = arg.exp;
|
|
cryrand_left = arg.left;
|
|
cryrand_bitcnt = arg.bitcnt;
|
|
cry_seed = arg.seed;
|
|
|
|
/*
|
|
* deal with the 0 integer arg - set the default initial state
|
|
*/
|
|
} else if (isint(arg) && arg == 0) {
|
|
cryrand_n = cryrand_init_n;
|
|
cryrand_r = pmod(cryrand_init_r, 2, cryrand_init_n);
|
|
cryrand_exp = cryrand_r;
|
|
cryrand_left = 0;
|
|
cryrand_bitcnt = 0;
|
|
cry_seed = srand(0);
|
|
}
|
|
|
|
/*
|
|
* return the previous state
|
|
*/
|
|
return (prev);
|
|
}
|
|
|
|
|
|
/*
|
|
* cryobj - how to initialize a cryobj object
|
|
*
|
|
* given:
|
|
* n product of Blum primes
|
|
* r quadratic residue of n=p*q
|
|
* exp used in computing crypto good bits
|
|
* left bits unused from the last cryrand() call
|
|
* bitcnt left contains bitcnt crypto good bits
|
|
* seed last seed set by srand() or 0
|
|
*
|
|
* return:
|
|
* an cryobj object
|
|
*
|
|
* NOTE: This function, by convention, returns an cryobj object.
|
|
*/
|
|
define
|
|
cryobj(n,r,exp,left,bitcnt,seed)
|
|
{
|
|
/* declare our objects */
|
|
local obj cryobj x;
|
|
|
|
/* firewall */
|
|
if (!isint(n) || !isint(r) || !isint(exp) || \
|
|
!isint(left) || !isint(bitcnt) || !isint(seed)) {
|
|
quit "bad args: first 7 args must be integers";
|
|
}
|
|
|
|
/* initialize object with default startup values */
|
|
x.n = n;
|
|
x.r = r;
|
|
x.exp = exp;
|
|
x.left = left;
|
|
x.bitcnt = bitcnt;
|
|
x.seed = seed;
|
|
|
|
/* return the initialized object */
|
|
return (x);
|
|
}
|
|
|
|
|
|
/*
|
|
* cmpobj - compare two cryrand objects
|
|
*
|
|
* usage:
|
|
* a an cryobj object
|
|
* b an cryobj object
|
|
*
|
|
* NOTE: This function is intended for debug purposes.
|
|
*/
|
|
define
|
|
cmpobj(a,b)
|
|
{
|
|
local obj cryobj x; /* firewall comparator */
|
|
|
|
/* firewall */
|
|
if (!istype(a, x)) {
|
|
quit "bad arg: 1st arg is not an cryobj object";
|
|
}
|
|
if (!istype(b, x)) {
|
|
quit "bad arg: 2nd arg is not an cryobj object";
|
|
}
|
|
|
|
/* compare values */
|
|
if (a.n != b.n) {
|
|
print "a.n - b.n:", a.n - b.n;
|
|
}
|
|
if (a.r != b.r) {
|
|
print "a.r - b.r:", a.r - b.r;
|
|
}
|
|
if (a.exp != b.exp) {
|
|
print "a.exp - b.exp:", a.exp - b.exp;
|
|
}
|
|
if (a.left != b.left) {
|
|
print "a.left - b.left:", a.left - b.left;
|
|
}
|
|
if (a.bitcnt != b.bitcnt) {
|
|
print "a.bitcnt - b.bitcnt:", a.bitcnt - b.bitcnt;
|
|
}
|
|
if (a.seed != b.seed) {
|
|
print "a.seed - b.seed:", a.seed - b.seed;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* cryobj_print - print the value of a cryobj object
|
|
*
|
|
* usage:
|
|
* a an cryobj object
|
|
*
|
|
* NOTE: This function is called automatically when an cryobj object
|
|
* is displayed.
|
|
*/
|
|
define
|
|
cryobj_print(a)
|
|
{
|
|
/* declare our objects */
|
|
local obj cryobj x; /* firewall comparator */
|
|
|
|
/* firewall */
|
|
if (!istype(a, x)) {
|
|
quit "bad arg: arg is not an cryobj object";
|
|
}
|
|
|
|
/* print the value */
|
|
print "cryobj(" : a.n : "," : a.r : "," : a.exp : "," : \
|
|
a.left : "," : a.bitcnt : "," : a.seed : ;
|
|
}
|
|
|
|
|
|
/*
|
|
* cryres - find a pseudo-random quadratic residue for scryrand() and cryrand()
|
|
*
|
|
* given:
|
|
* n product of two Blum primes
|
|
*
|
|
* returns:
|
|
* a number that is a quadratic residue of n=p*q
|
|
*
|
|
* This function is returns the pseudo-random quadratic residue of
|
|
* the product of two primes. Normally this function is called
|
|
* only by the crypto generator.
|
|
*
|
|
* NOTE: No check is made to ensure that the n is a product of Blum primes.
|
|
*/
|
|
define
|
|
cryres(n)
|
|
{
|
|
local quadres; /* quadratic residue of n */
|
|
local sqquadres; /* square of quadres mod n */
|
|
local minres; /* minimum residue allowed */
|
|
local maxres; /* maximum residue allowed */
|
|
local frac; /* n/frac that quadres is nearest */
|
|
local sqfrac; /* n/sqfrac that sqquadres is nearest */
|
|
local near; /* within +/- sqrt(n) is considered near */
|
|
local j;
|
|
|
|
/*
|
|
* firewall
|
|
*/
|
|
if (!isint(n)) {
|
|
quit "bad arg: must an integer";
|
|
}
|
|
if (n < 39601) {
|
|
/* see 'SOURCE OF MAGIC NUMBERS' for why we reject 39601=199*199 */
|
|
quit "bad arg: n < 199*199";
|
|
}
|
|
|
|
/*
|
|
* find a pseudo-random quadratic residue of n = p*q
|
|
*
|
|
* We will start sequentially searching for quadratic residue
|
|
* values starting at the initial search point 'ir', while at
|
|
* same time confining our search to the interval [2^sqrpow,n/2),
|
|
* where 2^sqrpow is the smallest power of 2 >= n^(3/4). This
|
|
* range helps us avoid selecting trivial residues.
|
|
*
|
|
* We will also reject any quadratic residue whose square mod n
|
|
* is outside of the [2^sqrpow,n/2) range, or whose square mod n
|
|
* is within sqrt(n) of itself.
|
|
*
|
|
* Finally, we reject any quadratic residue or square mod n of a
|
|
* quadratic residue that is within sqrt(n) of a simple fraction
|
|
* of n (n/k for some integer k).
|
|
*/
|
|
minres = 2^(highbit(floor(power(n,0.75)))+1);
|
|
maxres = (n//3)-1;
|
|
near = isqrt(n);
|
|
if (maxres-near <= minres) {
|
|
quit "bad arg: arg is too small";
|
|
}
|
|
j = 0;
|
|
do {
|
|
/* form a quadratic residue */
|
|
quadres = pmod(rand(minres,maxres+1), 2, n);
|
|
sqquadres = pmod(quadres, 2, n);
|
|
} while (++j < 100 && \
|
|
(quadres < minres || quadres > maxres || \
|
|
sqquadres < minres || sqquadres > maxres || \
|
|
abs((n//round(n/quadres)) - quadres) <= near || \
|
|
abs((n//round(n/sqquadres)) - sqquadres) <= near || \
|
|
abs(sqquadres-quadres) <= near));
|
|
if (j >= 100) {
|
|
quit "could not find a good quadradic residue after 100 tries";
|
|
}
|
|
|
|
/*
|
|
* return the quadratic residue of n
|
|
*/
|
|
return (quadres);
|
|
}
|
|
|
|
|
|
/*
|
|
* Initial read execution code
|
|
*/
|
|
cry_seed = srand(0); /* pre-initialize the tables */
|
|
global cryrand_ver = "25.3 95/11/17 05:33:31";
|
|
/* XXX - Don't forget update version number when all changes are checked in */
|
|
|
|
global lib_debug;
|
|
if (lib_debug >= 0) {
|
|
print "cryrand_ver:", cryrand_ver;
|
|
print "cryrand(len) defined";
|
|
print "scryrand([seed, [len1, len2]]) defined";
|
|
print "scryrand(seed, 0, in, ir) defined";
|
|
print "random([a, [b]]) defined";
|
|
print "srandom(seed) defined";
|
|
print "obj cryobj defined";
|
|
print "randstate([cryobj | 0]) defined";
|
|
}
|