/* 
 * Keyrand - 
 *  Time keystrokes, then mix the times together to produce a high quality
 *  random number.
 *  Written by Scott Nelson.  july 5, 1997
 *  and released to the public domain.
 *
 * This program calls two MSDOS specific functions, but similar functions
 * exist on almost all platforms:
 *
 * The kbhit routine returns 0 if no key has been pressed on the keyboard.
 * The getch() reads a key from the keyboard 
 *
 * Keyrand assumes that there is at least one bit of entropy in the
 * timing of keystrokes, which is fairly conservative.
 * 
 * The random numbers produced pass all tests I was able to put them to.
 *
 */


#include "stdio.h"
#include "conio.h"

/*
 * The Mix function uses a reverse CRC 
 * There are much faster ways to do this, but I chose this method because 
 * it's simple and relatively easy to understand.
 * The choice of 0xEDB88320l is not random, but any 32 bit number
 * with the 3 or more '1' bits and the high bit set would work about the same.
 */

unsigned long mix = 1;

void mix1(int bit) {
    if ((mix^bit) & 1)
        mix = (mix>>1) ^ 0xEDB88320l;
    else
        mix = (mix>>1);
}

void mix16(unsigned int word) {
    int i;

    for (i=0;i<16; i++) {
        mix1(word&1);
        word>>=1;
    }
}

int main() {
    int i;
    static int count = 0;

    printf("This program times keystrokes and produces 32 bit random numbers.\n");
    printf("press ESC to exit, or hit any other key(s) repeatedly.\n");

    for (;;) {    
        for (i=0; i<32; i++) {
            while (kbhit() == 0) {
                count++;
            }
            if (getch() == 27) {
		return 0;  /* Escape == ascii 27 */
	    }
    
            mix16(count);
        }
        printf("%08lx\n", mix);
    }
}