blob: 416b5dc53c1d3135b402a1a3283f82cc2399516c [file] [log] [blame]
drhae85dc82001-01-13 14:34:05 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhae85dc82001-01-13 14:34:05 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhae85dc82001-01-13 14:34:05 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drhae85dc82001-01-13 14:34:05 +000010**
11*************************************************************************
12** This file contains code to implement a pseudo-random number
13** generator (PRNG) for SQLite.
14**
15** Random numbers are used by some of the database backends in order
16** to generate random integer keys for tables or random filenames.
17**
drhb19a2bc2001-09-16 00:13:26 +000018** $Id: random.c,v 1.5 2001/09/16 00:13:27 drh Exp $
drhae85dc82001-01-13 14:34:05 +000019*/
20#include "sqliteInt.h"
drh17a68932001-01-31 13:28:08 +000021#include <time.h>
drhae85dc82001-01-13 14:34:05 +000022
23/*
24** Get a single 8-bit random value from the RC4 PRNG.
25*/
26int sqliteRandomByte(void){
27 int t;
28
29 /*
30 ** The following structure holds the current state of the RC4 algorithm.
31 ** We use RC4 as a random number generator. Each call to RC4 gives
32 ** a random 8-bit number.
33 **
34 ** Nothing in this file or anywhere else in SQLite does any kind of
35 ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
36 ** number generator) not as an encryption device.
37 */
38 static struct {
39 int isInit;
40 int i, j;
41 int s[256];
42 } prng_state;
43
44 /* Initialize the state of the random number generator once,
45 ** the first time this routine is called. The seed value does
46 ** not need to contain a lot of randomness since we are not
47 ** trying to do secure encryption or anything like that...
48 */
49 if( !prng_state.isInit ){
50 int i;
51 static char seed[] = " sqlite random seed";
52 char k[256];
53 time((time_t*)seed);
54 prng_state.j = 0;
55 prng_state.i = 0;
56 for(i=0; i<256; i++){
57 prng_state.s[i] = i;
58 k[i] = seed[i%sizeof(seed)];
59 }
60 for(i=0; i<256; i++){
61 int t;
62 prng_state.j = (prng_state.j + prng_state.s[i] + k[i]) & 0xff;
63 t = prng_state.s[prng_state.j];
64 prng_state.s[prng_state.j] = prng_state.s[i];
65 prng_state.s[i] = t;
66 }
67 prng_state.isInit = 1;
68 }
69
70 /* Generate and return single random byte
71 */
72 prng_state.i = (prng_state.i + 1) & 0xff;
73 prng_state.j = (prng_state.j + prng_state.s[prng_state.i]) & 0xff;
74 t = prng_state.s[prng_state.i];
75 prng_state.s[prng_state.i] = prng_state.s[prng_state.j];
76 prng_state.s[prng_state.j] = t;
77 t = prng_state.s[prng_state.i] + prng_state.s[prng_state.j];
drh5edc3122001-09-13 21:53:09 +000078 return prng_state.s[t & 0xff];
drhae85dc82001-01-13 14:34:05 +000079}
80
81/*
82** Return a random 32-bit integer. The integer is generated by making
83** 4 calls to sqliteRandomByte().
84*/
85int sqliteRandomInteger(void){
86 int r;
87 int i;
88 r = sqliteRandomByte();
89 for(i=1; i<4; i++){
90 r = (r<<8) + sqliteRandomByte();
91 }
92 return r;
93}
94
drh3fc190c2001-09-14 03:24:23 +000095/*
96** Return a random 16-bit unsigned integer. The integer is generated by
97** making 2 calls to sqliteRandomByte().
98*/
99int sqliteRandomShort(void){
100 int r;
101 r = sqliteRandomByte();
102 r = (r<<8) + sqliteRandomByte();
103 return r;
104}
drhae85dc82001-01-13 14:34:05 +0000105
106/*
107** Generate a random filename with the given prefix. The new filename
108** is written into zBuf[]. The calling function must insure that
109** zBuf[] is big enough to hold the prefix plus 20 or so extra
110** characters.
111**
112** Very random names are chosen so that the chance of a
113** collision with an existing filename is very very small.
114*/
115void sqliteRandomName(char *zBuf, char *zPrefix){
116 int i, j;
117 static const char zRandomChars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
118 strcpy(zBuf, zPrefix);
119 j = strlen(zBuf);
120 for(i=0; i<15; i++){
121 int c = sqliteRandomByte() % (sizeof(zRandomChars) - 1);
122 zBuf[j++] = zRandomChars[c];
123 }
124 zBuf[j] = 0;
125}