Merge pull request #555 from Knogle/xoroshiro256

Implement XORoshiro-256 PRNG for Enhanced Random Number Generation Efficiency
This commit is contained in:
PartialVolume
2024-03-21 22:10:14 +00:00
committed by GitHub
7 changed files with 258 additions and 15 deletions

View File

@@ -6,5 +6,5 @@ AM_LDFLAGS =
# this lists the binaries to produce, the (non-PHONY, binary) targets in
# the previous manual Makefile
bin_PROGRAMS = nwipe
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h alfg/add_lagg_fibonacci_prng.h alfg/add_lagg_fibonacci_prng.c pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.c
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h alfg/add_lagg_fibonacci_prng.h alfg/add_lagg_fibonacci_prng.c xor/xoroshiro256_prng.h xor/xoroshiro256_prng.c pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.c
nwipe_LDADD = $(PARTED_LIBS) $(LIBCONFIG)

View File

@@ -1600,6 +1600,7 @@ void nwipe_gui_prng( void )
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern nwipe_prng_t nwipe_aes_ctr_prng;
extern nwipe_prng_t nwipe_xoroshiro256_prng;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;
extern int terminate_signal;
@@ -1643,6 +1644,10 @@ void nwipe_gui_prng( void )
{
focus = 3;
}
if( nwipe_options.prng == &nwipe_xoroshiro256_prng )
{
focus = 4;
}
do
{
/* Clear the main window. */
@@ -1658,6 +1663,7 @@ void nwipe_gui_prng( void )
mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac64.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_add_lagg_fibonacci_prng.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_xoroshiro256_prng.label );
yy++;
/* Print the cursor. */
@@ -1740,6 +1746,7 @@ void nwipe_gui_prng( void )
tab1,
"Performs best on a 64-bit CPU. Use ISAAC if this system has a 32-bit CPU. " );
break;
case 3:
mvwprintw( main_window,
@@ -1783,6 +1790,54 @@ void nwipe_gui_prng( void )
tab1,
"applications requiring long sequences with a good speed-randomness trade-off. " );
break;
case 4:
mvwprintw( main_window,
yy++,
tab1,
"Xoroshiro256**, originally designed by David Blackman and Sebastiano Vigna" );
mvwprintw( main_window,
yy++,
tab1,
"for 128 bits, was adapted to 256 bits by Fabian Druschke. This adaptation " );
mvwprintw( main_window,
yy++,
tab1,
"enhances its capability for fast, high-quality generation of pseudo-random " );
mvwprintw( main_window,
yy++,
tab1,
"numbers with a state size of 256 bits. It boasts an extremely long period " );
mvwprintw( main_window,
yy++,
tab1,
"of 2^256-1 without sacrificing performance, suitable for a wide range of " );
mvwprintw( main_window,
yy++,
tab1,
"applications. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
mvwprintw( main_window,
yy++,
tab1,
"The simple arithmetic operations (shifts, rotations, and XORs) of " );
mvwprintw( main_window,
yy++,
tab1,
"Xoroshiro256** ensure low computational complexity. This, combined with " );
mvwprintw( main_window,
yy++,
tab1,
"the adaptation for 256 bits by Fabian Druschke, allows efficient use " );
mvwprintw( main_window,
yy++,
tab1,
"especially for legacy systems, due to its efficiency and minimal demands. " );
break;
}
/* switch */
@@ -1849,6 +1904,10 @@ void nwipe_gui_prng( void )
{
nwipe_options.prng = &nwipe_add_lagg_fibonacci_prng;
}
if( focus == 4 )
{
nwipe_options.prng = &nwipe_xoroshiro256_prng;
}
return;
case KEY_BACKSPACE:

View File

@@ -43,6 +43,7 @@ int nwipe_options_parse( int argc, char** argv )
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;
extern nwipe_prng_t nwipe_xoroshiro256_prng;
/* The getopt() result holder. */
int nwipe_opt;
@@ -496,6 +497,11 @@ int nwipe_options_parse( int argc, char** argv )
nwipe_options.prng = &nwipe_add_lagg_fibonacci_prng;
break;
}
if( strcmp( optarg, "xoroshiro256_prng" ) == 0 )
{
nwipe_options.prng = &nwipe_xoroshiro256_prng;
break;
}
/* Else we do not know this PRNG. */
fprintf( stderr, "Error: Unknown prng '%s'.\n", optarg );
@@ -546,6 +552,7 @@ void nwipe_options_log( void )
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;
extern nwipe_prng_t nwipe_xoroshiro256_prng;
/**
* Prints a manifest of options to the log.
@@ -597,26 +604,35 @@ void nwipe_options_log( void )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Mersenne Twister" );
}
if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Lagged Fibonacci generator (EXPERIMENTAL!)" );
}
else
{
if( nwipe_options.prng == &nwipe_isaac )
if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac" );
nwipe_log( NWIPE_LOG_NOTICE, " prng = Lagged Fibonacci generator (EXPERIMENTAL!)" );
}
else
{
if( nwipe_options.prng == &nwipe_isaac64 )
if( nwipe_options.prng == &nwipe_xoroshiro256_prng )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac64" );
nwipe_log( NWIPE_LOG_NOTICE, " prng = XORoshiro-256 (EXPERIMENTAL!)" );
}
else
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Undefined" );
if( nwipe_options.prng == &nwipe_isaac )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac" );
}
else
{
if( nwipe_options.prng == &nwipe_isaac64 )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac64" );
}
else
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Undefined" );
}
}
}
}
}

View File

@@ -26,6 +26,7 @@
#include "isaac_rand/isaac_rand.h"
#include "isaac_rand/isaac64.h"
#include "alfg/add_lagg_fibonacci_prng.h" //Lagged Fibonacci generator prototype
#include "xor/xoroshiro256_prng.h" //XORoshiro-256 prototype
nwipe_prng_t nwipe_twister = { "Mersenne Twister (mt19937ar-cok)", nwipe_twister_init, nwipe_twister_read };
@@ -36,6 +37,8 @@ nwipe_prng_t nwipe_isaac64 = { "ISAAC-64 (isaac64.c)", nwipe_isaac64_init, nwipe
nwipe_prng_t nwipe_add_lagg_fibonacci_prng = { "Lagged Fibonacci generator",
nwipe_add_lagg_fibonacci_prng_init,
nwipe_add_lagg_fibonacci_prng_read };
/* XOROSHIRO-256 PRNG Structure */
nwipe_prng_t nwipe_xoroshiro256_prng = { "XORoshiro-256", nwipe_xoroshiro256_prng_init, nwipe_xoroshiro256_prng_read };
/* Print given number of bytes from unsigned integer number to a byte stream buffer starting with low-endian. */
static inline void u32_to_buffer( u8* restrict buffer, u32 val, const int len )
@@ -258,14 +261,11 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE )
}
/* EXPERIMENTAL implementation of Lagged Fibonacci generator a lot of random numbers */
int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE )
{
nwipe_log( NWIPE_LOG_NOTICE, "Initialising Lagged Fibonacci generator PRNG" );
if( *state == NULL )
{
/* This is the first time that we have been called. */
nwipe_log( NWIPE_LOG_NOTICE, "Initialising Lagged Fibonacci generator PRNG" );
*state = malloc( sizeof( add_lagg_fibonacci_state_t ) );
}
add_lagg_fibonacci_init(
@@ -274,6 +274,22 @@ int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE )
return 0;
}
/* EXPERIMENTAL implementation of XORoroshiro256 algorithm to provide high-quality, but a lot of random numbers */
int nwipe_xoroshiro256_prng_init( NWIPE_PRNG_INIT_SIGNATURE )
{
nwipe_log( NWIPE_LOG_NOTICE, "Initialising XORoroshiro-256 PRNG" );
if( *state == NULL )
{
/* This is the first time that we have been called. */
*state = malloc( sizeof( xoroshiro256_state_t ) );
}
xoroshiro256_init(
(xoroshiro256_state_t*) *state, (unsigned long*) ( seed->s ), seed->length / sizeof( unsigned long ) );
return 0;
}
int nwipe_add_lagg_fibonacci_prng_read( NWIPE_PRNG_READ_SIGNATURE )
{
u8* restrict bufpos = buffer;
@@ -292,6 +308,33 @@ int nwipe_add_lagg_fibonacci_prng_read( NWIPE_PRNG_READ_SIGNATURE )
{
unsigned char temp_output[16]; // Temporary buffer for the last block
add_lagg_fibonacci_genrand_uint256_to_buf( (add_lagg_fibonacci_state_t*) *state, temp_output );
// Copy the remaining bytes
memcpy( bufpos, temp_output, remain );
}
return 0; // Success
}
int nwipe_xoroshiro256_prng_read( NWIPE_PRNG_READ_SIGNATURE )
{
u8* restrict bufpos = buffer;
size_t words = count / SIZE_OF_XOROSHIRO256_PRNG;
/* Loop to fill the buffer with blocks directly from the XORoroshiro256 algorithm */
for( size_t ii = 0; ii < words; ++ii )
{
xoroshiro256_genrand_uint256_to_buf( (xoroshiro256_state_t*) *state, bufpos );
bufpos += SIZE_OF_XOROSHIRO256_PRNG; // Move to the next block
}
/* Handle remaining bytes if count is not a multiple of SIZE_OF_XOROSHIRO256_PRNG */
const size_t remain = count % SIZE_OF_XOROSHIRO256_PRNG;
if( remain > 0 )
{
unsigned char temp_output[16]; // Temporary buffer for the last block
xoroshiro256_genrand_uint256_to_buf( (xoroshiro256_state_t*) *state, temp_output );
// Copy the remaining bytes
memcpy( bufpos, temp_output, remain );
}

View File

@@ -59,6 +59,10 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE );
int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_add_lagg_fibonacci_prng_read( NWIPE_PRNG_READ_SIGNATURE );
/* XOROSHIRO-256 prototypes. */
int nwipe_xoroshiro256_prng_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_xoroshiro256_prng_read( NWIPE_PRNG_READ_SIGNATURE );
/* Size of the twister is not derived from the architecture, but it is strictly 4 bytes */
#define SIZE_OF_TWISTER 4
@@ -69,4 +73,7 @@ int nwipe_add_lagg_fibonacci_prng_read( NWIPE_PRNG_READ_SIGNATURE );
/* Size of the Lagged Fibonacci generator is not derived from the architecture, but it is strictly 32 bytes */
#define SIZE_OF_ADD_LAGG_FIBONACCI_PRNG 32
/* Size of the XOROSHIRO-256 is not derived from the architecture, but it is strictly 32 bytes */
#define SIZE_OF_XOROSHIRO256_PRNG 32
#endif /* PRNG_H_ */

View File

@@ -0,0 +1,74 @@
/*
* XORoshiro-256 PRNG Implementation
* Author: Fabian Druschke
* Date: 2024-03-13
*
* This is a XORoshiro-256 (XOR/rotate/shift/rotate) pseudorandom number generator
* implementation, designed for fast and efficient generation of high-quality
* pseudorandom numbers. XORoshiro-256 is part of the XORoshiro family of PRNGs known
* for their simplicity and excellent statistical properties for a wide range of
* applications, though they are not suitable for cryptographic purposes due to their
* predictability.
*
* As the author of this implementation, I, Fabian Druschke, hereby release this work into
* the public domain. I dedicate any and all copyright interest in this work to the public
* domain, making it free to use for anyone for any purpose without any conditions, unless
* such conditions are required by law.
*
* This software is provided "as is", without warranty of any kind, express or implied,
* including but not limited to the warranties of merchantability, fitness for a particular
* purpose, and noninfringement. In no event shall the authors be liable for any claim,
* damages, or other liability, whether in an action of contract, tort, or otherwise, arising
* from, out of, or in connection with the software or the use or other dealings in the software.
*
* Note: This implementation does not utilize OpenSSL or any cryptographic libraries, as
* XORoshiro-256 is not intended for cryptographic applications. It is crucial for applications
* requiring cryptographic security to use a cryptographically secure PRNG.
*/
#include "xoroshiro256_prng.h"
#include <stdint.h>
#include <string.h>
void xoroshiro256_init( xoroshiro256_state_t* state, uint64_t init_key[], unsigned long key_length )
{
// Initialization logic; ensure 256 bits are properly seeded
for( int i = 0; i < 4; i++ )
{
if( i < key_length )
{
state->s[i] = init_key[i];
}
else
{
// Example fallback for insufficient seeds; consider better seeding strategies
state->s[i] = state->s[i - 1] * 6364136223846793005ULL + 1;
}
}
}
static inline uint64_t rotl( const uint64_t x, int k )
{
return ( x << k ) | ( x >> ( 64 - k ) );
}
void xoroshiro256_genrand_uint256_to_buf( xoroshiro256_state_t* state, unsigned char* bufpos )
{
// This part of the code updates the state using xoroshiro256**'s algorithm.
const uint64_t result_starstar = rotl( state->s[1] * 5, 7 ) * 9;
const uint64_t t = state->s[1] << 17;
state->s[2] ^= state->s[0];
state->s[3] ^= state->s[1];
state->s[1] ^= state->s[2];
state->s[0] ^= state->s[3];
state->s[2] ^= t;
state->s[3] = rotl( state->s[3], 45 );
// Note: 'result_starstar' was only used for demonstration purposes and is not part of the
// original Xoroshiro256** specification. Here, we write the complete state into the buffer.
// Ensure that 'bufpos' has enough storage space (256 bits / 32 bytes).
memcpy( bufpos, state->s, 32 ); // Copies the entire 256-bit (32 bytes) state into 'bufpos'
}

View File

@@ -0,0 +1,44 @@
/*
* XORoshiro-256 PRNG Definitions
* Author: Fabian Druschke
* Date: 2024-03-13
*
* This header file contains definitions for the XORoshiro-256 pseudorandom number generator
* (PRNG) implementation. XORoshiro-256 is part of the XORoshiro family of PRNGs, known for
* their simplicity, efficiency, and high-quality pseudorandom number generation suitable for
* a wide range of applications, excluding cryptographic purposes due to its predictable nature.
*
* As the author of this work, I, Fabian Druschke, hereby release this work into the public
* domain. I dedicate any and all copyright interest in this work to the public domain, making
* it free to use for anyone for any purpose without any conditions, unless such conditions are
* required by law.
*
* This software is provided "as is", without warranty of any kind, express or implied,
* including but not limited to the warranties of merchantability, fitness for a particular
* purpose, and noninfringement. In no event shall the authors be liable for any claim,
* damages, or other liability, whether in an action of contract, tort, or otherwise, arising
* from, out of, or in connection with the software or the use or other dealings in the software.
*
* Note: This implementation does not utilize any cryptographic libraries, as XORoshiro-256 is
* not intended for cryptographic applications. It is crucial for applications requiring
* cryptographic security to use a cryptographically secure PRNG.
*/
#ifndef XOROSHIRO256_PRNG_H
#define XOROSHIRO256_PRNG_H
#include <stdint.h>
// Structure to store the state of the xoroshiro256** random number generator
typedef struct xoroshiro256_state_s
{
uint64_t s[4];
} xoroshiro256_state_t;
// Initializes the xoroshiro256** random number generator with a seed
void xoroshiro256_init( xoroshiro256_state_t* state, uint64_t init_key[], unsigned long key_length );
// Generates a 256-bit random number using xoroshiro256** and stores it directly in the output buffer
void xoroshiro256_genrand_uint256_to_buf( xoroshiro256_state_t* state, unsigned char* bufpos );
#endif // XOROSHIRO256_PRNG_H