Back to index

php5  5.3.10
random.c
Go to the documentation of this file.
00001 /*
00002 ** 2001 September 15
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** This file contains code to implement a pseudo-random number
00013 ** generator (PRNG) for SQLite.
00014 **
00015 ** Random numbers are used by some of the database backends in order
00016 ** to generate random integer keys for tables or random filenames.
00017 **
00018 ** $Id: random.c 195361 2005-09-07 15:11:33Z iliaa $
00019 */
00020 #include "sqliteInt.h"
00021 #include "os.h"
00022 
00023 
00024 /*
00025 ** Get a single 8-bit random value from the RC4 PRNG.  The Mutex
00026 ** must be held while executing this routine.
00027 **
00028 ** Why not just use a library random generator like lrand48() for this?
00029 ** Because the OP_NewRecno opcode in the VDBE depends on having a very
00030 ** good source of random numbers.  The lrand48() library function may
00031 ** well be good enough.  But maybe not.  Or maybe lrand48() has some
00032 ** subtle problems on some systems that could cause problems.  It is hard
00033 ** to know.  To minimize the risk of problems due to bad lrand48()
00034 ** implementations, SQLite uses this random number generator based
00035 ** on RC4, which we know works very well.
00036 */
00037 static int randomByte(){
00038   unsigned char t;
00039 
00040   /* All threads share a single random number generator.
00041   ** This structure is the current state of the generator.
00042   */
00043   static struct {
00044     unsigned char isInit;          /* True if initialized */
00045     unsigned char i, j;            /* State variables */
00046     unsigned char s[256];          /* State variables */
00047   } prng;
00048 
00049   /* Initialize the state of the random number generator once,
00050   ** the first time this routine is called.  The seed value does
00051   ** not need to contain a lot of randomness since we are not
00052   ** trying to do secure encryption or anything like that...
00053   **
00054   ** Nothing in this file or anywhere else in SQLite does any kind of
00055   ** encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
00056   ** number generator) not as an encryption device.
00057   */
00058   if( !prng.isInit ){
00059     int i;
00060     char k[256];
00061     prng.j = 0;
00062     prng.i = 0;
00063     sqliteOsRandomSeed(k);
00064     for(i=0; i<256; i++){
00065       prng.s[i] = i;
00066     }
00067     for(i=0; i<256; i++){
00068       prng.j += prng.s[i] + k[i];
00069       t = prng.s[prng.j];
00070       prng.s[prng.j] = prng.s[i];
00071       prng.s[i] = t;
00072     }
00073     prng.isInit = 1;
00074   }
00075 
00076   /* Generate and return single random byte
00077   */
00078   prng.i++;
00079   t = prng.s[prng.i];
00080   prng.j += t;
00081   prng.s[prng.i] = prng.s[prng.j];
00082   prng.s[prng.j] = t;
00083   t += prng.s[prng.i];
00084   return prng.s[t];
00085 }
00086 
00087 /*
00088 ** Return N random bytes.
00089 */
00090 void sqliteRandomness(int N, void *pBuf){
00091   unsigned char *zBuf = pBuf;
00092   sqliteOsEnterMutex();
00093   while( N-- ){
00094     *(zBuf++) = randomByte();
00095   }
00096   sqliteOsLeaveMutex();
00097 }