// PureNoise CryptoLib (c) 1997-2004, PureNoise Ltd Vaduz // // CryptoLib Chaos 2002 (Six-In-One) Package Version 1.96 // // Recommended compilation parameters: // // Pentium Pro code, optimized for speed, 4 or 8 byte aligned, multithreaded; GCC: -O3 -fomit-frame-pointer #include #include #include #include #if defined (WIN32) || defined (_WIN32) || defined (WIN32_WINNT) || defined (_WIN32_WINNT) || defined (__WIN32__) || defined (WINDOWS) || defined (_WINDOWS) #include #include #define sleep_1ms() Sleep(1) #else #include static __forceinline void __fastcall sleep_1ms (void) { struct timespec req = {1, 100000}; struct timespec rem; nanosleep (&req, &rem); } #endif /// Keeping Chaos RNG constantly reseeded with a lot of entropy in the background is as simple as that static void __cdecl reseeding (void *x) { for (;;) { rand32 (); sleep_1ms (); } } int __cdecl main (void) { unsigned long i, k; /// index variables unsigned long data[16]; /// data storage unsigned long key[128]; /// key storage unsigned long hash[128]; /// hash storage unsigned long secret[128]; /// PRNG internal state unsigned long seed = 0x7BED1AFD; /// PRNG initialization seed chaos_prng prng = {secret, 128}; /// PRNG pointers chaos_prng stream = {secret, 128}; /// STREAM cipher pointers FILE *f; /// RNG/PRNG output file unsigned __int64 cb, ce; /// It's more secure to kick off a self-reseeding thread on startup /// It's only recommended where large secret key generation is required /// As soon as the new thread starts, chaos_init will be called automatically _beginthread (reseeding, 0, NULL); /// /// 1) To use as a block cipher for blocks of data of any size: /// /// Some key for (k = 0; k < 128; k++) key[k] = k * 0x7BED1AFD; /// Some data strcpy ((char *) data, "BLOCK CIPHER TEST OK"); /// Encrypting 5*32 = 160 bit of data with a 128*32 = 4096 bit key chaos_block (data, 5, key, 128); /// Decrypting the same block of data with the same key order_block (data, 5, key, 128); /// Let's see what we've got there printf ("\"%s\"\n", data); /// /// 2,3) To use as a HASH or a MAC function: /// /// Setting the initial HASH value to a constant value for a HASH or to a secret value for a MAC /// It could be all 0's, but it better be a more or less uniformly distributed set of bits for (k = 0; k < 32; k++) ((unsigned char *)hash)[k] = (unsigned char) k*0x7B+0xED; /// Some data strcpy ((char *) data, "HASH TEST INPUT"); // for a MAC also attach the key /// Hashing 4*32 = 128 bit of data into a 8*32 = 256 bit hash chaos_block (hash, 8, data, 4); // 256 bit HASH of "HASH TEST INPUT" // chaos_block (hash, 8, data, 4 + 128); // 256 bit MAC of "HASH TEST INPUT" with a 128*32 = 4096 bit key //or // chaos_block (hash, 8, data, 4); // 256 bit MAC of "HASH TEST INPUT" // chaos_block (hash, 8, key, 128); // with a 128*32 = 4096 bit key //just make sure the key is hashed in after the data, not before it /// Printing out the resulting HASH printf ("HASH of \"%s\" is\n", data); for (k = 0; k < 16; k++) printf (" %02X", ((unsigned char *)hash)[k]); printf ("\n"); for (k = 16; k < 32; k++) printf (" %02X", ((unsigned char *)hash)[k]); printf ("\n"); /// /// 4) To use as a stream cipher: /// /// Some key for (k = 0; k < 17; k++) key[k] = k * 0x7BED1AFD; /// Some data strcpy ((char *) data, "STREAM CIPHER TEST OK"); /// Initializing the PRNG's internal state with a 17*32 = 544 bit key pseudo_chaos_init (&stream, key, 17); /// Encrypting 6*32 = 192 bit of data with a 17*32 = 544 bit key and a 128*32 = 4096 bit internal state for (i = 0; i < 6; i++) data[i] ^= chaos_rand32 (&stream, key, 17); /// Initializing the PRNG's internal state with the same key pseudo_chaos_init (&stream, key, 17); /// Decrypting the same block of data with the same stream for (i = 0; i < 6; i++) data[i] ^= chaos_rand32 (&stream, key, 17); /// Let's see what we've got there printf ("\"%s\"\n", data); /// /// 5) To use as a hassle-free fast Random Number Generator: /// if (!(f = fopen ("RANDOM.BIN", "wb"))) goto _norng; printf ("Saving random data into RANDOM.BIN for DIEHARD tests.\n"); for (i = 0; i < 0x6000; i++) { for (k = 0; k < 128; k++) data[k] = rand32 (); // it's self-initializing; no need to call chaos_init (); fwrite (data, 128, 4, f); } fclose (f); _norng: /// /// 6) To use as a PRNG: /// if (!(f = fopen ("PRNG.BIN", "wb"))) goto _noprng; /// Initializing the PRNG's internal state with one 32-bit seed pseudo_chaos_init (&prng, &seed, 1); printf ("Saving pseudo-random data into PRNG.BIN for DIEHARD tests.\n"); for (i = 0; i < 0x6000; i++) { for (k = 0; k < 128; k++) data[k] = chaos_rand32 (&prng, prng.key, 128); fwrite (data, 128, 4, f); } fclose (f); _noprng: printf ("DONE.\n"); return 0; }