Short: CSPRNG/PRNG/RNG DOS Handler for AmigaOS Author: Diego Casorran Uploader: diegocr at users.sf.net Type: util/cli Version: 1.0 Architecture: m68k-amigaos > 3.0 Random-Handler is a Native DOS Handler for AmigaOS to produce sequences of random bytes, mostly used on cryptography or related applications. The Handler has been designed to allow the use of various different types of RNGs (Random Number Generators) by just providing a filename or other, as well other ways to change it interactively, and even the seed values. This handler has been developed on an A1200 with AmigaOS v3.5 and a Blizzard 68060 board, The Random Generators has been optimized where possible to pass the Chi-Square tests (some unsucesfull, as you'll see), check the file benchmarks.txt to see my own results and feel free to send me your report by running the randomtest tool in the hope to perform some optimizations. _______________________________________________________________________________ ------------------------------------------------------------------------------- Random-Handler Glosary: RNG: Random Number Generator PRNG: Pseudo Random Number Generator CSPRNG: Cryptographically Secure Pseudo Random Number Generator ENT: Shell tool (created by John 'Random' Walker) which applies various tests to sequences of bytes for evaluate entropy per byte, compressibility, arithmetic mean value, etc _______________________________________________________________________________ ------------------------------------------------------------------------------- Random Generators Supported and/or created for this Handler: 1 Single generator using FastRand() This is a "must" in the sense to implement what is available on our OS, but the random data generating by this function is really a crap.. if you need to known more about it check the amiga.lib docs. The read buffer is filled peforming iterations of 32-bits. 2 Single generator using RangeRand() Same as FastRand(), RangeRand() however works slower but it generates better entropy, it does iterations of 16-bits, this can be improved/optimized but we decided to keep it as-is for legacy reasons... 3 Mouse movements (plus XOR deviations) This isnt a real RNG by itself but on how it has been created generates a good entropy, more or less faster (less than more..), and the most important thing is that the Chi-Square test is reasonable passed compared to others RNGs, ofcouse that the mouse can't be quiet to generate something good. How the mouse movements are detected is just reading the Custom chips registers, which values are recorded then incrementally XORed and that filled to the read buffer on iterations of 16-bits. 4 CIA / Custom / etc things This works on a similar way to Mouse movements, it reads various Amiga's hardware registers which used to generate the random data. 5 Linear Congruential Generator Generates 2**31-2 random numbers, based on "Random Number Generators: Good Ones Are Hard to Find", S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988), and "Two Fast Implementations of the 'Minimal Standard' Random Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), p. 87-88 Uses L. Schrage's method to avoid overflow problems. 6 McGill Super-Duper RNG The McGill Super-Duper Random Number Generator, incorporates the Ziggurat method of sampling from decreasing... Created by K. Ananthanarayana, N. Paul, G. Marsaglia, W.W. Tsang and which has been rewritted into C by E. Schneider. 7 Marsaglia's algorithm This method implements the concatenation of following two 16-bit multiply with carry x(n)=a*x(n-1)+carry mod 2^16 and y(n)=b*y(n-1)+carry mod 2^16 number and carry packed within the same 32 bit integer. Algorithm recommended by Marsaglia from the diehard tests. 8 Combination of three tausworth generators. Source: Pierre L'Ecuyer, "Maximally Equidistributed Combined Tausworthe Generators". Mathematics of Computation, vol.65, no.213(1996), pp203--213. 9 Twisted GFSR generator A twisted GFSR generator with an unusually long peroid. (2^800) 10 Default IBBA generator. An implementation of Robert Jenkins' IBAA (Indirection, Barrelshift, Accumulate, and Add) generator. Very fast and it seems excellent. The read buffer is filled with iterations of 32-bits, such integers are obtained from a private pool of 1024 bytes 11 Own IBBA Generator Optimized IBAA Generator which shifts 128-bits per iteration, this is done by using a two-side pool which makes it work faster. 12 Mersenne Twister A newer twisted GFSR generator with an incredibly long period of 2^19937. The read buffer is filled on iterations of 64-bits using a private pool (such pool can contain a maximun of 624 ULONGs) 13 CSPRNG from Amiga's ExecBase A funny method of Cryptographicaly Secure random data generation, very good but slow.. It reads the System's Exec base on chunks of ULONG, which are used later as keys to generate the cryptographically random numbers. (This is a BETA RNG and should be revised and optimized..) If you like to see some other algorithm implemented on the handler just request it and we will study it. _______________________________________________________________________________ ------------------------------------------------------------------------------- Usage: Normal usage from programs is just using the normal dos.library functions, Open() -> Read() -> Close(), remember this is a system-friendly DOS Handler, hence you can even use "type random: >ram:entropy" without problems at all! Hence to use the handler from AmigaDOS command line tools just follow the instructions from the first packet description ( ACTION_FIND#? / Open() ). The supported DOS Packets by the handler are the follow: ACTION_FINDINPUT ACTION_FINDUPDATE ACTION_FINDOUTPUT These packets implements the Open() function, from the filename to be openend you can chose what RNG to use and even the Seed value which internally will be used to the whole generators... To Select the RNG type, use "rX" where X is the id number assigned as above mentioned. To the Seed value, use "sXYZ" where XYZ is a decimal value for the new Seed to be used internally by the RNGS, that value should be from 1 to 4294967296. To Enable Cryptographically Secure Random Numbers put "c" AT THE END of the filename, ie: RANDOM:r4c, that will crypt the data generated by RNG #4, If what you want is to just generate a quick and safe sequence, ie: for digital-fingerprint usage, just use RANDOM:c, where is the secret key to use to generate such sequence. NOTE that if you use "c" or "c" that MUST be at the end of the filename or it will not work properly!... examples: Open( "RANDOM:r3", MODE_NEWFILE) Will open the random stream type 3 (Mouse movements) Open( "ranDOm:r2s245786633", MODE_NEWFILE) Will open the random stream 2, and use 245786633 as the initial seed value. Open( "RANDOM:r2s245786633c", MODE_NEWFILE) Same as above but the random data is crypted. Open("random:", MODE_NEWFILE) Will use the default RNG and Seed (the initial seed value used by default comes from the E-Clock) Open( "Random:cNoMeJodas", MODE_NEWFILE ) Will generate a Cryptographically Secure Sequence using as secret key "NoMeJodas" ACTION_READ This packet implements the Read() function, not much to say, it is obvious how it works (see the example at below if so) ACTION_WRITE This packet implements the Write() function, note that you can't write to the ramdom stream, obviously. It is implemented as a way to propagate more unpredictable results... When you have open a random stream, if you want to reinitialize the seeder, you may think on doing Close() -> Open("random:rXsXYZ",0), you can do that to give a known(!) new seed value, however is faster (and will be less predictable) just using: Write(fh, mydata, mydatalen); The CRC CheckSum of 'mydata' will be used to reinitialize the internal seeder. ACTION_SEEK ACTION_SET_FILE_SIZE These two packets, like ACTION_WRITE, are just wrappers to other behaviors which aren't the default. Using Seek() on a open random stream is used to change interactively the RNG type, without the need to re-opened a new file. ie: Seek( fh, 4, 0); will change the fh's RNG type to 4 (note that even if you try to use a wrong type it will fall back to the default one) NOTE: the value returned by Seek() is the seed currently in use!, therefore if what you want is to obtain such value only, just use Seek(fh,-1,0); ACTION_LOCATE_OBJECT ACTION_FREE_LOCK These packets are but aren't here... ;-) ACTION_INFO ACTION_DISK_INFO These two packets are implemented as fun mainly... The number of blocks are the number of times a RNG worked, and the BytesPerBlock the average random bytes which have been generated since the random: device was mounted. (therefore, if you like to know how many random data have been generated just use (NumBlocks * BytesPerBlock) :o) ACTION_END ACTION_DIE These packets implements Close() and UnMount ... nothing more to say. _______________________________________________________________________________ ------------------------------------------------------------------------------- Code Examples: 1) Normal Usage to obtain random data int main( void ) { BPTR fh; if((fh = Open( "RANDOM:r3", MODE_NEWFILE))) { APTR buffer; ULONG buflen; buflen = 1024; if((buffer = AllocMem( buflen+1, MEMF_ANY ))) { if(Read( fh, buffer, buflen ) == buflen) { while(buflen-- > 0) Printf("%02lx", *((UBYTE *)buffer)++); } FreeMem( buffer, 1025 ); } Close( fh ); } PrintFault( IoErr(), "something failed"); return(EXIT_SUCCESS); } 2) Cryptographically Secure Sequence for digital-fingerprint int main(int argc, char * argv[] ) { BPTR fh; UBYTE file[34], dfg[16]; if( argc != 2 ) { Printf("Usage: %s \a\n",(long) argv[0] ); return(EXIT_FAILURE); } snprintf( file, sizeof(file)-1, "RANDOM:c%s", argv[1] ); if((fh = Open( file, MODE_NEWFILE))) { if(Read( fh, dfg, sizeof(dfg)) == sizeof(dfg)) { int x; Printf("Your digital-fingerprint for key \"%s\"" " is:\n",(long) &file[8] ); for( x = 0 ; x < sizeof(dfg) ; x++ ) Printf("%02lX",(long) dfg[x] ); PutStr("\n"); } Close( fh ); } PrintFault( IoErr(), "something failed"); return(EXIT_SUCCESS); } _______________________________________________________________________________ ------------------------------------------------------------------------------- Installation: Cd into the "Handler" folder as found into the archive and copy the "RAMDOM" mount-list file to SYS:Devs/DOSDrivers or to SYS:Storage/DOSDrivers, and the random-handler file to L:, when finished use "Mount RANDOM:" to actvate it. _______________________________________________________________________________ ------------------------------------------------------------------------------- Usefull Links: http://random.mat.sbg.ac.at/~charly/server/node3.html http://www.derkeiler.com/Newsgroups/sci.crypt/2004-09/0880.html http://www.mathcom.com/corpdir/techinfo.mdir/scifaq/q210.html http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html http://senderek.de/security/secret-key.protection.html http://www.iro.umontreal.ca/~simardr/indexe.html http://citeseer.ist.psu.edu/context/35616/0 http://www.csis.hku.hk/~diehard/ http://www.fourmilab.ch/random/ http://csrc.nist.gov/rng/ http://amiga.sourceforge.net/ .. :-) _______________________________________________________________________________ ------------------------------------------------------------------------------- History: Arround the year 2003, when Ive started coding on C, one of my various first projects was to create a file handle which generates random data to be used on my OpenSSH port, since ixemul.library lacks a /dev/random unit, then looking the net for examples and docs on how to create Handlers ive found a good example (on the fish disks, IIRC), Empty-handler created by Oliver Wagner, that handler does nothing apart creating a zeroed file, but let me understand how works internatelly the File Handlers for AmigaOS, well, with that example as base of my work Ive started imagining how to generate proper entropy data... First thing Ive tested was just using the lame FastRand() function, but his data sucks too much therefore with some help from the E-Clock values as to the seeds it was a bit better.. but however it was still a shit (4.2 bits per byte, or so). Then I decided to change how to generate the random data, but hey... why a handler should manage only a type of data? indeed here I chossed that handler will be able to manage not a single entropy generator, depending the filename given it will decide what to use, ie random:r1 random:r2 etc, certain cases will require a faster random data generator only and not the better entropy which generated slowy, hence thats the way to do it. well, happily ;) ive continued implementing a new RNG, now testing how RangeRand() does his work... it worked more slowy than FastRand() (well, the function names says all ;-), but indeed was much better, 7.8 bits per byte of entropy!, wow, almost prefect!... At this step the 0.1 version of the handler was ready, working fine..and stable :-) However, although it worked well, I wasn't satisfied... and looking the net Ive found some PD-RNGs (Public Domain Random Number Generators) which Ive integrated into the handler as well, they was fex a LCG (Linear congruential generator) By Ray Gardner (based on "Random Number Generators: Good Ones Are Hard to Find", and "Two Fast Implementations of the 'Minimal Standard' Random Number Generator"), Or The McGill Super-Duper Random Number Generator (Incorporating the Ziggurat method of sampling from decreasing or symmetric unimodal density functions), both methods worked on a similar way for entropy (about 7.8 bits per byte as well) but lots faster than RangeRand()! ... Unfortunatelly on the 2004, due some issue I can't remember right now - and due others projects comming - Ive stoped further improving of the handler and finally wasn't publically released, and these days (yeah, two years later!) just remembered this handler after an idea of creating a new handler comes to my mind, and to be again familiar with Handlers I decided to rewrite almost from scrach this random-handler, and in addition optimizing it all as possible... and well... here is the result, hope you like it! :-) btw, I give a BIG thanks to the people mentioned here, this Handler was possible thanks to your previous work!... _______________________________________________________________________________ ------------------------------------------------------------------------------- Licence: Random-Handler, Copyright (c)2006 Diego Casorran All rights reserved. Random-Handler is FREEWARE, do what you want with it, but there is no warranty of any kind, use it at your own risk. if you would like to pay/donate anything for it I'll appreciate it, but instead you can go to http://amiga.sf.net/ and click on the Google Adverts, that will be fine for me as well, thanks :-)