📄 truerand.c
字号:
/* * Physically random numbers (very nearly uniform) * D. P. Mitchell * Modified by Matt Blaze 2/95 * Assembled and reformatted by Ralf S. Engelschall for mod_ssl *//* * The authors of this software are Don Mitchell and Matt Blaze. * Copyright (c) 1995 by AT&T. * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software and in all copies of the supporting * documentation for such software. * * This software may be subject to United States export controls. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. *//* * WARNING: depending on the particular platform, truerand() output may * be biased or correlated. In general, you can expect about 16 bits of * "pseudo-entropy" out of each 32 bit word returned by truerand(), * but it may not be uniformly diffused. You should therefore run * the output through some post-whitening function (like MD5 or DES or * whatever) before using it to generate key material. (RSAREF's * random package does this for you when you feed truerand() bits to the * seed input function.) * * Test these assumptions on your own platform before fielding a system * based on this software or these techniques. * * This software seems to work well (at 16 bits per truerand() call) on * a Sun Sparc-20 under SunOS 4.1.3 and on a P100 under BSDI 2.0. You're * on your own elsewhere. */#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <setjmp.h>#include <math.h>#include <sys/time.h>static jmp_buf env;static unsigned count;static unsigned ocount;static unsigned buffer;static int tick(void){ struct itimerval it, oit; timerclear(&it.it_interval); it.it_value.tv_sec = 0; it.it_value.tv_usec = 16665; if (setitimer(ITIMER_REAL, &it, &oit) < 0) perror("tick");}static void interrupt(int s){ if (count) longjmp(env, 1); (void) signal(SIGALRM, interrupt); tick();}static unsigned long roulette(void){ if (setjmp(env)) { count ^= (count >> 3) ^ (count >> 6) ^ ocount; count &= 0x7; ocount = count; buffer = (buffer << 3) ^ count; return buffer; } (void) signal(SIGALRM, interrupt); count = 0; tick(); for (;;) count++; /* about 1 MHz on VAX 11/780 */}unsigned long truerand(void){ count = 0; (void) roulette(); (void) roulette(); (void) roulette(); (void) roulette(); (void) roulette(); (void) roulette(); (void) roulette(); (void) roulette(); (void) roulette(); (void) roulette(); return roulette();}int n_truerand(int n){ int slop, v; slop = 0x7FFFFFFF % n; do { v = truerand() >> 1; } while (v <= slop); return v % n;}/* * Secure Hash Standard * proposed NIST SHS * coded for byte strings: number of bits is a multiple of 8 * * Copyright (c) 1992, 1994 AT&T Bell Laboratories * Coded by Jim Reeds 5 Feb 1992 * Enhanced by Jack Lacy 1993, 1994 *//* * unsigned char * shs(char *s, int n); * * input: * s character array to be hashed * n length of s in BYTES * output: * return value: address of 5 unsigned longs holding hash * * machine dependencies: * assumes a char is 8 bits *//* * passes test on: * gauss (vax) * 3k (cray) * slepian (MIPS) * bird (sparcstation II) */#include <sys/types.h>#include <stdio.h>typedef struct { long totalLength; unsigned long h[5]; unsigned long w[80];} SHS_CTX;unsigned char *shs();#ifdef SOLARIS2X#define bzero(b, l) memset(b, 0, l)#define bcopy(s, d, l) memcpy(d, s, l)#define bcmp(s, d, l) (memcmp(s, d, l)? 1 : 0)#endifstatic long nbits;static unsigned long *h;static unsigned long *w;static void shs1();#define MASK (unsigned long)0xffffffffL /* in case more than 32 bits per long *//* * stick one byte into the current block; process the block when full */static void opack(unsigned char c){ int n32, nd32, shiftbits; register unsigned long x, mask, y; nd32 = (int) (nbits >> 5); /* nbits/32 */ n32 = (int) (nbits & 0x1f); /* nbits%32 */ shiftbits = 24 - n32; x = (unsigned long) (c << shiftbits); mask = (unsigned long) (0xff << shiftbits); mask = ~mask; y = w[nd32]; y = (y & mask) + x; w[nd32] = y; nbits += 8; if (nbits == 512) { nbits = 0; shs1(); }}static void pack(unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3){ int nd32; nd32 = (int) (nbits >> 5); w[nd32] = (u_long) (((u_long) c0 << 24) | ((u_long) c1 << 16) | ((u_long) c2 << 8) | (u_long) c3); nbits += 32; if (nbits == 512) { nbits = 0; shs1(); }}/* * stick a 4 byte number into the current block */static void packl(unsigned long x){ pack((unsigned char) (x >> 24), (unsigned char) (x >> 16), (unsigned char) (x >> 8), (unsigned char) (x >> 0));}/* * process one block */static void shs1(void){ unsigned long *wp; unsigned long temp; unsigned long A, B, C, D, E; int t;#define S(n,x) (u_long)(((x)<<(n))|((MASK&(x))>>(32-(n)))) wp = w; t = 8; do { wp[16] = S(1, (u_long) (wp[13] ^ wp[8] ^ wp[2] ^ wp[0])); wp[17] = S(1, (u_long) (wp[14] ^ wp[9] ^ wp[3] ^ wp[1])); wp[18] = S(1, (u_long) (wp[15] ^ wp[10] ^ wp[4] ^ wp[2])); wp[19] = S(1, (u_long) (wp[16] ^ wp[11] ^ wp[5] ^ wp[3])); wp[20] = S(1, (u_long) (wp[17] ^ wp[12] ^ wp[6] ^ wp[4])); wp[21] = S(1, (u_long) (wp[18] ^ wp[13] ^ wp[7] ^ wp[5])); wp[22] = S(1, (u_long) (wp[19] ^ wp[14] ^ wp[8] ^ wp[6])); wp[23] = S(1, (u_long) (wp[20] ^ wp[15] ^ wp[9] ^ wp[7])); wp += 8; t--; } while (t > 0); A = h[0]; B = h[1]; C = h[2]; D = h[3]; E = h[4]; t = 0; while (t < 20) { temp = S(5, A) + E + w[t++]; temp += (unsigned long) 0x5a827999L + ((B & C) | (D & ~B)); E = D; D = C; C = S(30, B); B = A; A = temp; } while (t < 40) { temp = S(5, A) + E + w[t++]; temp += (unsigned long) 0x6ed9eba1L + (B ^ C ^ D); E = D; D = C; C = S(30, B); B = A; A = temp; } while (t < 60) { temp = S(5, A) + E + w[t++]; temp += (unsigned long) 0x8f1bbcdcL + ((B & C) | (B & D) | (C & D)); E = D; D = C; C = S(30, B); B = A; A = temp; } while (t < 80) { temp = S(5, A) + E + w[t++]; temp += (unsigned long) 0xca62c1d6L + (B ^ C ^ D); E = D; D = C; C = S(30, B); B = A; A = temp; } h[0] = MASK & (h[0] + A); h[1] = MASK & (h[1] + B); h[2] = MASK & (h[2] + C); h[3] = MASK & (h[3] + D); h[4] = MASK & (h[4] + E);}#define CHARSTOLONG(wp,s,i) \ {*wp++ = \ (u_long)((((u_long)(s[i])&0xff)<<24)| \ (((u_long)(s[i+1])&0xff)<<16)| \ (((u_long)(s[i+2])&0xff)<<8)| \ (u_long)(s[i+3]&0xff));}void shsInit(SHS_CTX *mdContext){ nbits = 0; mdContext->h[0] = (unsigned long) 0x67452301L; mdContext->h[1] = (unsigned long) 0xefcdab89L; mdContext->h[2] = (unsigned long) 0x98badcfeL; mdContext->h[3] = (unsigned long) 0x10325476L; mdContext->h[4] = (unsigned long) 0xc3d2e1f0L; mdContext->totalLength = 0;}void shsUpdate(SHS_CTX *mdContext, unsigned char *s, unsigned int n){ register unsigned long *wp; long nn = n; long i; w = mdContext->w; h = mdContext->h; mdContext->totalLength += n; nbits = 0; n = n / (u_long) 64; wp = w; while (n > 0) { CHARSTOLONG(wp, s, 0); CHARSTOLONG(wp, s, 4); CHARSTOLONG(wp, s, 8); CHARSTOLONG(wp, s, 12); CHARSTOLONG(wp, s, 16); CHARSTOLONG(wp, s, 20); CHARSTOLONG(wp, s, 24); CHARSTOLONG(wp, s, 28); CHARSTOLONG(wp, s, 32); CHARSTOLONG(wp, s, 36); CHARSTOLONG(wp, s, 40); CHARSTOLONG(wp, s, 44); CHARSTOLONG(wp, s, 48); CHARSTOLONG(wp, s, 52); CHARSTOLONG(wp, s, 56); CHARSTOLONG(wp, s, 60); n--; wp = w; s = (s + 64); shs1(); } i = nn % 64; while (i > 3) { CHARSTOLONG(wp, s, 0); s = (s + 4); nbits += (u_long) 32; i -= 4; } while (i) { opack((unsigned char) *s++); i--; }}void shsFinal(SHS_CTX *mdContext){ long nn = mdContext->totalLength; w = mdContext->w; h = mdContext->h; opack(128); while (nbits != 448) opack(0); packl((unsigned long) (nn >> 29)); packl((unsigned long) (nn << 3)); /* if(nbits != 0) handle_exception(CRITICAL,"shsFinal(): nbits != 0\n"); */}unsigned char *shs(unsigned char *s, long n){ SHS_CTX *mdContext; static SHS_CTX mdC; static unsigned char ret[20]; int i; mdContext = &mdC; shsInit(mdContext); shsUpdate(mdContext, s, n); shsFinal(mdContext); for (i = 0; i < 5; i++) { ret[i * 4] = (mdContext->h[i] >> 24) & 0xff; ret[i * 4 + 1] = (mdContext->h[i] >> 16) & 0xff; ret[i * 4 + 2] = (mdContext->h[i] >> 8) & 0xff; ret[i * 4 + 3] = (mdContext->h[i]) & 0xff; } return ret;}unsigned long *fShsDigest(FILE *in){ SHS_CTX *mdContext; SHS_CTX mdC; unsigned char buffer[1024]; long length, total; mdContext = &mdC; bzero(buffer, 1024); total = 0; shsInit(mdContext); while ((length = fread(buffer, 1, 1024, in)) != 0) { total += length; shsUpdate(mdContext, buffer, length); } shsFinal(mdContext); return mdContext->h;}/* * Random byte interface to truerand() * Matt Blaze 5/95 * eight really random bits * usage: * unsigned char r; int randbyte(); * r=randbyte(); * randbyte() takes about .3 seconds on most machines. */int randbyte(void){ unsigned long truerand(); unsigned char *shs(); unsigned long r[2]; unsigned char *hash; r[0] = truerand(); r[1] = truerand(); hash = shs((unsigned char *)r, (long)sizeof(r));#ifdef DEBUGRND printf("%011o %011o %02x\n", r[0], r[1], *hash & 0xff);#endif return ((int) (*hash)) & 0xff;}/* * Main program *//* SIGPIPE causes normal exit */static void handler(int sig){ exit(0);}int main(int argc, char **argv){ int count; signal(SIGPIPE, handler); if (argc == 1) count = 0; else count = atoi(argv[1]) + 1; setbuf(stdout, NULL); while (--count) fprintf(stdout, "%c", randbyte());}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -