> >After that, you actually want to feed the entropy you're getting
> >from the radio tuner *into* /dev/[u]random.
>
> He may wish to pre-process the raw bits to remove any potential
> bias they may have.
>
> Here's what I do for random bits:
> http://www.etoan.com/random-number-generation/index.html
Nice!!! :) I wasn't aware such electronics is so cheap!
Here is the final version of the OTP generator:
Hints and constructive criticism welcomed.
News: Elementary sanity check on input data is performed.
//-- cut here ----------------- makernd.c ------------------ cut here ----
/*
## #######################################################################
##
## makernd - program for generation of random files suitable for one-time
## pads. Uses audio signal from soundcard input.
##
## Performs basic sanity check for sufficient entropy on the input.
## Reads 64 bytes from DSP, checks if there is at least one pair of
## adjanced bytes where the bytes are different by more than 16
## (arbitrarily chosen value). This should be replaced with some kind
## of statistical analysis. The check is also done on each block read
## from the input, discarding suspicious input data.
##
## Reads blocks of 128 bytes from RANDOMINPUT, hashes them with MD5,
## outputs 16-byte blocks to output file and RANDOMDEV (so as the side
## effect it feeds the entropy pool).
##
## Takes one mandatory parameter (number of random bytes to produce) and
## one optional parameter (output file name - uses stdout if not present).
##
## #######################################################################
*/
#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>
#define RANDOMDEV "/dev/urandom"
#define RANDOMINPUT "/dev/dsprandom"
char output[18];
FILE*fo,*frnd;
void outputbinary(char*s,long n)
{ while(n>0)
{fprintf(fo,"%c",s[0] & 0xff);s++;n--;}
}
// FIXME: Replace with real statistical check
int isinsufficiententropy(char*data,int n)
{ int t;
for(t=0;t<n-1;t++)if(abs((data[t+1]&0xff)-(data[t]&0xff))>16)return 0;
return 1;
}
int checkinputentropy(FILE*f)
{ char data[64];
fread(data,64,1,f);
return isinsufficiententropy(data,64);
}
int output16bytes(FILE*f,long n)
{ char data[128];
MD5_CTX c;
MD5_Init(&c);
MD5_Update(&c,output,16);
for(;;){fread(data,128,1,f);
if(!isinsufficiententropy(data,128))break;
fprintf(stderr,"Insufficient input entropy. Rereading block.\n");}
MD5_Update(&c,data,128);
MD5_Final(output,&c);
if(n>16)n=16;if(n<0)n=0;
outputbinary(output,n);
if(frnd)fwrite(output,16,1,frnd);
return 0;
}
int main(int argc,char*argv[])
{
FILE*f;
long n;
if(argc<2)
{printf("makernd <LENGTH> [output.file]\n"
"Creates LENGTH bytes of random numbers derived from "RANDOMINPUT", "
"which should be a symlink to eg. /dev/dsp0 fed with analog signal "
"from eg. a white noise generator.\n"
"Outputs to stdout if output.file is not specified.\n"
"Feeds the output also to "RANDOMDEV".\n");
return 0;}
n=atol(argv[1]);
if(n<=0)
{fprintf(stderr,"Argument '%s' has to be greater than zero.\n",argv[1]);
return 111;}
f=fopen(RANDOMINPUT,"r");
if(!f)
{perror("ERROR: Cannot open "RANDOMINPUT);
fprintf(stderr,"Check if the symlink or device exists.\n");
return 111;}
if(checkinputentropy(f))
{fprintf(stderr,"ERROR: Input entropy seems to be insufficient.\n"
"No two adjanced bytes in "RANDOMINPUT" that are different by more
than 16.\n"
"Check the input signal volume.\n"
"Cowardly refusing to create any output.\n");
return 1;}
frnd=fopen(RANDOMDEV,"rw");
if(frnd){fread(output,16,1,frnd);}
else{fprintf(stderr,"Cannot open "RANDOMDEV", cannot initialize output. Proceeding
anyway.\n");}
if(argc>2){fo=fopen(argv[2],"w");
if(!fo){perror("ERROR: Cannot open output file");return(111);}}
else fo=stdout;
while(n>0){output16bytes(f,n);n-=16;}
fclose(f);fclose(frnd);
return 0;
}