commit 32fce58a6569d641143503f996b8c98c9956c4d2
Author: Michael Savage <mikejsavage@gmail.com>
Date: Sat, 28 Dec 2019 12:41:26 +0200
Initial commit
Diffstat:
A | README.md | | | 60 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | ggentropy.cpp | | | 108 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | ggentropy.h | | | 23 | +++++++++++++++++++++++ |
3 files changed, 191 insertions(+), 0 deletions(-)
diff --git a/README.md b/README.md
@@ -0,0 +1,60 @@
+# ggentropy
+
+ggentropy is a liberally licensed, cross platform, entropy library for
+C++. You can use it to generate cryptographically secure random numbers,
+safe for use as nonces and keys in cryptographic operations.
+
+ggentropy supports Windows, MacOS, Linux and OpenBSD.
+
+
+## Usage
+
+ggentropy has one function:
+
+```cpp
+bool ggentropy( void * buf, size_t n );
+```
+
+which writes `n` bytes of crytographically secure random data to `buf`.
+It returns true on success and false on failure. Some platforms place a
+length restriction on `n`, so the library will exit on all platforms if
+`n` is greater than 256.
+
+Basic usage looks like this:
+
+```cpp
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include "ggentropy.h"
+
+int main() {
+ uint8_t entropy[ 16 ];
+ if( !ggentropy( entropy, sizeof( entropy ) ) )
+ return 1;
+
+ for( size_t i = 0; i < sizeof( entropy ); i++ ) {
+ printf( "%02" PRIx8, entropy[ i ] );
+ }
+ printf( "\n" );
+
+ return 0;
+}
+```
+
+`ggentropy` can fail. In long lived programs you should use it to seed a
+userspace cryptographically secure psuedo-random number generator once
+at program startup and use that for all future cryptographically secure
+random data. For example, you can encrypt a stream of zeroes using a key
+chosen by ggentropy, and use the output of the cipher as a random number
+source.
+
+
+## Implementation details
+
+ggentropy uses the following functionality:
+
+- Windows: [CryptGenRandom](https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom)
+- MacOS: /dev/urandom
+- Linux: getrandom with a fallback to /dev/urandom
+- OpenBSD: arc4random_buf
diff --git a/ggentropy.cpp b/ggentropy.cpp
@@ -0,0 +1,108 @@
+/*
+ * ggentropy
+ *
+ * Copyright (c) 2019 Michael Savage <mike@mikejsavage.co.uk>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined( _WIN32 )
+# define PLATFORM_WINDOWS 1
+#elif defined( __linux__ )
+# define PLATFORM_LINUX 1
+#elif defined( __APPLE__ )
+# define PLATFORM_MACOS 1
+#elif defined( __OpenBSD__ )
+# define PLATFORM_OPENBSD 1
+#else
+# error new platform
+#endif
+
+#include <assert.h>
+
+#if PLATFORM_LINUX || PLATFORM_MACOS
+
+#include <stdio.h>
+
+static bool try_urandom( void * buf, size_t n ) {
+ assert( n <= 256 );
+
+ FILE * f = fopen( "/dev/urandom", "r" );
+ if( f == NULL )
+ return false;
+
+ size_t ok = fread( buf, 1, n, f );
+ fclose( f );
+
+ return ok == n;
+}
+
+#endif
+
+#if PLATFORM_WINDOWS
+
+#include <windows.h>
+#include <wincrypt.h>
+
+bool ggentropy( void * buf, size_t n ) {
+ assert( n <= 256 );
+
+ HCRYPTPROV provider;
+ if( CryptAcquireContext( &provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == 0 )
+ return false;
+
+ int ok = CryptGenRandom( provider, n, ( BYTE * ) buf );
+ CryptReleaseContext( provider, 0 );
+
+ return ok != 0;
+}
+
+#elif PLATFORM_LINUX
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+bool ggentropy( void * buf, size_t n ) {
+ assert( n <= 256 );
+
+ int ok = syscall( SYS_getrandom, buf, n, 0 );
+ if( ok >= 0 && size_t( ok ) == n )
+ return true;
+
+ if( errno != ENOSYS )
+ return false;
+
+ return try_urandom( buf, n );
+}
+
+#elif PLATFORM_MACOS
+
+bool ggentropy( void * buf, size_t n ) {
+ assert( n <= 256 );
+ return try_urandom( buf, n );
+}
+
+#elif PLATFORM_OPENBSD
+
+#include <stdlib.h>
+
+bool ggentropy( void * buf, size_t n ) {
+ assert( n <= 256 );
+ arc4random_buf( buf, n );
+ return true;
+}
+
+#else
+#error new platform
+#endif
diff --git a/ggentropy.h b/ggentropy.h
@@ -0,0 +1,23 @@
+/*
+ * ggentropy
+ *
+ * Copyright (c) 2019 Michael Savage <mike@mikejsavage.co.uk>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#pragma once
+
+#include <stddef.h>
+
+bool ggentropy( void * buf, size_t n );