Skip to content

Commit

Permalink
Merge pull request #556 from Knogle/fibonacci
Browse files Browse the repository at this point in the history
Implemented Lagged Fibonacci generator PRNG providing high-speed, medium-quality numbers.
  • Loading branch information
PartialVolume authored Mar 21, 2024
2 parents cb595e1 + 0d01503 commit d40c28b
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 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 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)
79 changes: 79 additions & 0 deletions src/alfg/add_lagg_fibonacci_prng.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Additive Lagged Fibonacci Generator (ALFG) Implementation
* Author: Fabian Druschke
* Date: 2024-03-13
*
* This is an implementation of the Additive Lagged Fibonacci Generator (ALFG),
* a pseudorandom number generator known for its simplicity and good statistical properties
* for a wide range of applications. ALFGs are particularly noted for their long periods
* and efficiency in generating sequences of random numbers. However, like many other PRNGs,
* 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 is designed for non-cryptographic applications and should not be
* used where cryptographic security is required.
*/

#include "add_lagg_fibonacci_prng.h"
#include <stdint.h>
#include <string.h>

#define STATE_SIZE 64 // Size of the state array, sufficient for a high period
#define LAG_BIG 55 // Large lag, e.g., 55
#define LAG_SMALL 24 // Small lag, e.g., 24
#define MODULUS ( 1ULL << 48 ) // Modulus for the operations, here 2^48 for simple handling

void add_lagg_fibonacci_init( add_lagg_fibonacci_state_t* state, uint64_t init_key[], unsigned long key_length )
{
// Simple initialization: Fill the state with the key values and then with a linear combination of them
for( unsigned long i = 0; i < STATE_SIZE; i++ )
{
if( i < key_length )
{
state->s[i] = init_key[i];
}
else
{
// Simple method to generate further state values. Should be improved for serious applications.
state->s[i] = ( 6364136223846793005ULL * state->s[i - 1] + 1 ) % MODULUS;
}
}
state->index = 0; // Initialize the index for the first generation
}

void add_lagg_fibonacci_genrand_uint256_to_buf( add_lagg_fibonacci_state_t* state, unsigned char* bufpos )
{
uint64_t* buf_as_uint64 = (uint64_t*) bufpos; // Interprets bufpos as a uint64_t array for direct assignment
int64_t result; // Use signed integer to handle potential negative results from subtraction

for (int i = 0; i < 4; i++) {
// Subtract the two previous numbers in the sequence
result = (int64_t)state->s[(state->index + LAG_BIG) % STATE_SIZE] - (int64_t)state->s[(state->index + LAG_SMALL) % STATE_SIZE];

// Handle borrow if result is negative
if (result < 0) {
result += MODULUS;
// Optionally set a borrow flag or adjust the next operation based on borrow logic
}

// Store the result (after adjustment) back into the state, ensuring it's positive and within range
state->s[state->index] = (uint64_t)result;

// Write the result into buf_as_uint64
buf_as_uint64[i] = state->s[state->index];

// Update the index for the next round
state->index = (state->index + 1) % STATE_SIZE;
}
}

43 changes: 43 additions & 0 deletions src/alfg/add_lagg_fibonacci_prng.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Additive Lagged Fibonacci Generator (ALFG) Implementation definitions
* Author: Fabian Druschke
* Date: 2024-03-13
*
* This is an implementation of the Additive Lagged Fibonacci Generator (ALFG),
* a pseudorandom number generator known for its simplicity and good statistical properties
* for a wide range of applications. ALFGs are particularly noted for their long periods
* and efficiency in generating sequences of random numbers. However, like many other PRNGs,
* 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 is designed for non-cryptographic applications and should not be
* used where cryptographic security is required.
*/

#ifndef ADD_LAGG_FIBONACCI_PRNG_H
#define ADD_LAGG_FIBONACCI_PRNG_H

#include <stdint.h>

// State definition for the Additive Lagged Fibonacci Generator
typedef struct
{
uint64_t s[64]; // State array
unsigned int index; // Current index in the state array
} add_lagg_fibonacci_state_t;

// Function prototypes
void add_lagg_fibonacci_init( add_lagg_fibonacci_state_t* state, uint64_t init_key[], unsigned long key_length );
void add_lagg_fibonacci_genrand_uint256_to_buf( add_lagg_fibonacci_state_t* state, unsigned char* bufpos );

#endif // ADD_LAGG_FIBONACCI_PRNG_H
61 changes: 58 additions & 3 deletions src/gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -1599,10 +1599,13 @@ void nwipe_gui_prng( void )
extern nwipe_prng_t nwipe_twister;
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_add_lagg_fibonacci_prng;

extern int terminate_signal;

/* The number of implemented PRNGs. */
const int count = 3;
const int count = 4;

/* The first tabstop. */
const int tab1 = 2;
Expand Down Expand Up @@ -1636,7 +1639,10 @@ void nwipe_gui_prng( void )
{
focus = 2;
}

if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng )
{
focus = 3;
}
do
{
/* Clear the main window. */
Expand All @@ -1651,6 +1657,7 @@ void nwipe_gui_prng( void )
mvwprintw( main_window, yy++, tab1, " %s", nwipe_twister.label );
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 );
yy++;

/* Print the cursor. */
Expand Down Expand Up @@ -1733,8 +1740,52 @@ 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:

} /* switch */
mvwprintw( main_window,
yy++,
tab1,
"ALFG (Additive Lagged Fibonacci Generator), is a class of PRNGs utilizing" );
mvwprintw( main_window,
yy++,
tab1,
"the Fibonacci sequence with additive operations between lagged values. While" );
mvwprintw( main_window,
yy++,
tab1,
"they offer a good balance between speed and randomness, it's important to note" );
mvwprintw( main_window,
yy++,
tab1,
"that they provide lower levels of security, making them less suitable for" );
mvwprintw( main_window,
yy++,
tab1,
"cryptographic applications. Their periodicity depends on the choice of lags" );
mvwprintw( main_window,
yy++,
tab1,
"and arithmetic operations, potentially achieving large values, often 2^N or" );
mvwprintw( main_window,
yy++,
tab1,
"higher, where N is the bit length of the states. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
mvwprintw( main_window,
yy++,
tab1,
"Efficient on CPUs of any bit width, particularly suited for non-cryptographic" );
mvwprintw( main_window,
yy++,
tab1,
"applications requiring long sequences with a good speed-randomness trade-off. " );
break;
}

/* switch */

/* Add a border. */
box( main_window, 0, 0 );
Expand Down Expand Up @@ -1794,6 +1845,10 @@ void nwipe_gui_prng( void )
{
nwipe_options.prng = &nwipe_isaac64;
}
if( focus == 3 )
{
nwipe_options.prng = &nwipe_add_lagg_fibonacci_prng;
}
return;

case KEY_BACKSPACE:
Expand Down
14 changes: 13 additions & 1 deletion src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ int nwipe_options_parse( int argc, char** argv )
extern nwipe_prng_t nwipe_twister;
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;

/* The getopt() result holder. */
int nwipe_opt;
Expand Down Expand Up @@ -490,6 +491,11 @@ int nwipe_options_parse( int argc, char** argv )
nwipe_options.prng = &nwipe_isaac64;
break;
}
if( strcmp( optarg, "add_lagg_fibonacci_prng" ) == 0 )
{
nwipe_options.prng = &nwipe_add_lagg_fibonacci_prng;
break;
}

/* Else we do not know this PRNG. */
fprintf( stderr, "Error: Unknown prng '%s'.\n", optarg );
Expand Down Expand Up @@ -539,6 +545,7 @@ void nwipe_options_log( void )
extern nwipe_prng_t nwipe_twister;
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;

/**
* Prints a manifest of options to the log.
Expand Down Expand Up @@ -590,6 +597,11 @@ 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 )
Expand Down Expand Up @@ -681,7 +693,7 @@ void display_help()
puts( " -l, --logfile=FILE Filename to log to. Default is STDOUT\n" );
puts( " -P, --PDFreportpath=PATH Path to write PDF reports to. Default is \".\"" );
puts( " If set to \"noPDF\" no PDF reports are written.\n" );
puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac|isaac64)\n" );
puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac|isaac64|add_lagg_fibonacci_prng)\n" );
puts( " -q, --quiet Anonymize logs and the GUI by removing unique data, i.e." );
puts( " serial numbers, LU WWN Device ID, and SMBIOS/DMI data" );
puts( " XXXXXX = S/N exists, ????? = S/N not obtainable\n" );
Expand Down
48 changes: 48 additions & 0 deletions src/prng.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@
#include "mt19937ar-cok/mt19937ar-cok.h"
#include "isaac_rand/isaac_rand.h"
#include "isaac_rand/isaac64.h"
#include "alfg/add_lagg_fibonacci_prng.h" //Lagged Fibonacci generator prototype

nwipe_prng_t nwipe_twister = { "Mersenne Twister (mt19937ar-cok)", nwipe_twister_init, nwipe_twister_read };

nwipe_prng_t nwipe_isaac = { "ISAAC (rand.c 20010626)", nwipe_isaac_init, nwipe_isaac_read };
nwipe_prng_t nwipe_isaac64 = { "ISAAC-64 (isaac64.c)", nwipe_isaac64_init, nwipe_isaac64_read };

/* ALFG PRNG Structure */
nwipe_prng_t nwipe_add_lagg_fibonacci_prng = { "Lagged Fibonacci generator",
nwipe_add_lagg_fibonacci_prng_init,
nwipe_add_lagg_fibonacci_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 )
{
Expand Down Expand Up @@ -250,3 +256,45 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE )

return 0;
}

/* 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. */
*state = malloc( sizeof( add_lagg_fibonacci_state_t ) );
}
add_lagg_fibonacci_init(
(add_lagg_fibonacci_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;
size_t words = count / SIZE_OF_ADD_LAGG_FIBONACCI_PRNG;

/* Loop to fill the buffer with blocks directly from the Fibonacci algorithm */
for( size_t ii = 0; ii < words; ++ii )
{
add_lagg_fibonacci_genrand_uint256_to_buf( (add_lagg_fibonacci_state_t*) *state, bufpos );
bufpos += SIZE_OF_ADD_LAGG_FIBONACCI_PRNG; // Move to the next block
}

/* Handle remaining bytes if count is not a multiple of SIZE_OF_ADD_LAGG_FIBONACCI_PRNG */
const size_t remain = count % SIZE_OF_ADD_LAGG_FIBONACCI_PRNG;
if( remain > 0 )
{
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
}
7 changes: 7 additions & 0 deletions src/prng.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,18 @@ int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE );
int nwipe_isaac64_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE );

/* ALFG prototypes. */
int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_add_lagg_fibonacci_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

/* Size of the isaac/isaac64 is not derived from the architecture, but it is strictly 4 or 8 bytes */
#define SIZE_OF_ISAAC 4
#define SIZE_OF_ISAAC64 8

/* 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

#endif /* PRNG_H_ */
4 changes: 2 additions & 2 deletions src/temperature.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

//#define _LARGEFILE64_SOURCE
//#define _FILE_OFFSET_BITS 64
// #define _LARGEFILE64_SOURCE
// #define _FILE_OFFSET_BITS 64
#define _BSD_SOURCE

#include <stdio.h>
Expand Down

0 comments on commit d40c28b

Please sign in to comment.