Skip to content

Cryptographically secure, hardware-generated RNG written in NASM x86-64 assembly.

License

Notifications You must be signed in to change notification settings

jflopezfernandez/random-nasm-x86-64

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

random-nasm-x86-64

Cryptographically secure, hardware-generated random number provider-interface written in NASM x86-64 assembly.

Overview

The current version on the master branch (version 3.0.1) produces an executable 8,528 bytes long. It initially used the printf function by calling GCC and linking with glibc, which meant an unfortunate amount of size bloat because of all of the setup, shutdown, and miscellaneous helper code that gcc's main function and linking to the standard library imply. The goal is to reduce the size of the executable as much as possible to allow other programs the maximum cache space possible, while providing an extremely lightweight, low-memory footprint interface for generating cryptographically secure, statistically uniform random numbers.

The current version does not use the C Standard Library at all; instead, writing to standard output is done directly via system calls by writing everything in x86-64 assembly. The application currently returns an unsigned long long integer (64 bits) which it prints to standard output, but eventually the goal is to allow for minimum and maximum parameters to be set, as well as querying the interface for a specific number of outputs instead of having to call it for one at a time.

My plan at the moment is still to write the program in assembly language, but then manually edit the binary to change the location of the section headers and text section, as most of the executable at the moment is just empty space, which is an absolute waste. As an aside, the makefile has the --strip-all option specified, but for some reason it isn't actually doing it, so I appended a call to the stip utility to explicitly do it, and the program is now actually being stripped of its static symbol tables, so even with the added functionality of the rudimentary command-line option parsing, the new version of the program is actually eight (8) bytes smaller, so that was pretty cool.

Progress

Executable Size Status Date Changelog
16,848 bytes Functional 02 Jun 2019 Initial build, using gcc
16,504 bytes Functional 02 Jun 2019 Stripped debug symbols, removed superfluous code
4,336 bytes No Output 02 Jun 2019 Removed gcc helper code completely, no glibc, printf, etc.
8,536 bytes Functional 02 Jun 2019 Correctly outputting cryptographically secure, hardware-generated random numbers with no calls to glibc
8,528 bytes Functional 16 Jun 2019 Added rudimentary argument parsing, still experimental

Building

The application uses the Netwide Assembler (NASM) for compilation and GNU ld as the linker. To build the application, simply clone the repository run make in the project directory. The makefile uses the vpath variable to find the source files in the included src directory.

$ git clone https://github.com/jflopezfernandez/random-nasm-x86-64.git random
$ cd random
$ make

Note: As an assembly application, it is not portable without making some changes to the source. These are platform dependent and will vary, but at the very least you will for sure have to change the value of RAX before every syscall from what I have to whatever your system uses, depending on whether you are using Windows or MacOS.

Using

Having built the application, you can run it from the project directory by calling it like you normally would from bash:

$ ./random
4912874162021245581

I have not added a make install feature yet, but you can literally just copy the executable to your /usr/bin or /usr/local/bin directories if you want to. The application has no software dependencies, so provided you're on a Linux system and your CPU has the RDRAND instruction, you should be golden.

The RDRAND instruction was introduced by Intel in 2012 with its Ivy Bridge processors, so as long as your processor is newer than about that time, you should be okay.

I set up a bash script to generate n random numbers while I implement the functionality natively, and it looks something like this.

#!/bin/sh

if [[ "$#" -ne 1 ]]
then
    echo "Usage: rand [n]"
    exit
fi

for (( i = 0; i < $1; i++ ))
do
    random
done

Assuming you're still either in the project directory, or random is in your PATH, you should get something like this:

$ rand
Usage: rand [n]
$ rand 10
8499345643546254815
2694828518955488459
8325431899581510166
8656937487568858518
1048997955614388542
6484560130390556974
2065750195224245233
4070076239724635225
8734172364984907491
4674330604802842582

You can then pipe this output to wherever you need it to go.

Randomness

The following is a plot of a sample run of the program. The program was invoked using the command random 1000, which results in the sequential generation of one thousand random numbers.

Generated Random Numbers

In this plot, the n-th random number generated was plotted against its position in the output vector (i.e., its index).

The generated data used for the plot is publicly accessible and may be downloaded using this link.

Issues

Issue ID Type Description Status
Issue #1 Error Add check for RDRAND return value Closed
Issue #2 Feature Add invocation args for generating multiple RNs Open
Issue #3 Feature Add invocation arg for printing current application version Open

About

Cryptographically secure, hardware-generated RNG written in NASM x86-64 assembly.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published