Rolling Custom Cryptographic Systems: Part 2

For those who haven't read my original post (located HERE, we will be picking up where we left off in the design and implementation of our very own cryptosystem by implementing a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG).

What's The Point Of This?

For any of our cryptographic functions to have any use whatsoever, we need a stream of random information we can feed our algorithms so we can properly perform hashing functions, symmetrical and asymmetrical encryption.

The “secret sauce” behind encryption is that it looks like random, garbled data or can pose as data belonging to something else.

Why Can't I Just Use The random() Function?

Sadly, the random() function, as implemented in many languages, is not Cryptographically Secure and is actually rather predictable based on a variety of factors, like CPU performance and timings.

In the same vein, CSPRNGs are also rather methodical due to the nature of the hardware and need thorough testing.

Cool, So What Are We Going to Do?

Since efficiency and using stable code is key to making everything work properly, we will want to utilize an already existing library. In our case, we'll use Duthomhas's CSPRNG, located here. This will give us an API to work with, without worrying about how we'll generate random numbers.

But How Do CSPRNGs Work???

Generally, a CSPRNG would gather entropy (randomness) through a variety of sources, for example the difference in microseconds between keystrokes or the noise of a transmission, and use fancy mathematics like the modulus operator and exponentiation to produce much, much more entropic data quickly.

However, since we're lazy (Guilty is Charged!!!), we don't want to spend weeks developing a Cryptographically Secure Pseudo-Random Number Generator, we want to work on encryption.

Adding The API

The sample source code explains the usage of the C headers by adding the code and then using the following code sample to generate pseudo-random numbers:

 #include <stdio.h>
 #include <duthomhas/csprng.h>

 int main()
 {
   CSPRNG rng = csprng_create( rng ); // Constructor
   if (!rng)
   {
     fprintf( stderr, "%s\n", "No CSPRNG! Fooey!" );
     return 1;
   }

  long n = csprng_get_int( rng ); // Get an int

  double f;      // Get a double
  csprng_get( rng, &f, sizeof(f) );

  int xs[ 20 ];           // Get an array
  csprng_get( rng, xs, sizeof(xs) );

  void* p = malloc(20);     // et cetera
  csprng_get( rng, p, 20 );
  free( p );

  rng = csprng_destroy( rng );   // Destructor
  return 0;
}

This Code sample shows us that we can dynamically call csprng_get() to fill different data types with pseudo-random information. This will fit our needs immensely in a separate function, as such:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "duthomhas/csprng.h"

extern int csprng_get(CSPRNG, void* dest, unsigned long long size);
extern CSPRNG csprng_destroy(CSPRNG);

// Our implementation of the CSPRNG
void * randstuff(void * x) {
  CSPRNG rng = csprng_create( rng ); // create CSPRNG
  if (!rng) { 
    //if the CSPRNG fails to load
    fprintf( stderr, "%s\n", "No CSPRNG! Crap." );
    exit(1); //crash and return an error
  }

  csprng_get(rng, &x, sizeof(x)); // use CSPRNG
  rng = csprng_destroy(rng); // destroy the CSPRNG

  return x;
}

// Main function
int main(void) {
  char rand[50]; //To be filled with random garbage

  strcpy(rand, randstuff(rand));

  return 0;
}

This sample of code sadly isn't enough to get the CSPRNG working, as there's a slight flaw in the API we were provided in the csprng.c file. To fix this we need to swap the line that says #include <duthomhas/csprng.h> with #include "duthomhas/csprng.h" and everything should compile.

Alright, So What Did You Do?

We took sample code, and modified it to suit our purposes. Of course, our program doesn't yet work 100% and we're getting segmentation faults. However, this is a great first step as we're now able to produce pseudo-randomness at will.

To be more precise, we created a function called randstuff() that allows us to produce pseudorandom binary data at will. On top of this, we made the functions take the void * data type, allowing us to pass any form of data that we please into the function. This is somewhat dangerous and we'll need to explicitly convert our data to use the function later down the road... However, it provides us with the facilities necessary to create random information necessary for encryption.

Finally, since all this is placed into a separate function, we can call it anywhere we need randomness.

Be sure to stick around for Part 3, where we implement a hashing function!

Liked This Content? Check Out Our Discord Community and Become an email subscriber!