GithubHelp home page GithubHelp logo

randombytes's Introduction

Pluggable randombytes function

GitHub Actions

randombytes is a library that exposes a single function for retrieving crypto-secure random bytes. It is loosely based on Libsodium's random bytes API. If you can, you should use that one. Otherwise, you can use this library.

Usage

randombytes takes two arguments:

  1. A pointer to the buffer
  2. The length of the buffer in bytes

The function will always return an int which will be 0 on success. The caller must check this. If some kind of error occured, errno MAY contain a hint to what the error was, and a subsequent call to the randombytes function MAY succeed. An example of when the function may fail is when /dev/urandom could not be opened, because there were no file descriptors left to use for the process.

On sensible systems (like the ones with arc4random) the latency is very low. However, this is totally not guaranteed. Do not expect this function to be very fast. Benchmark for your specific setup, and use a fast CSPRNG if you need.

Example code:

#include "randombytes.h"
#include <inttypes.h>
#include <stdio.h>

int main()
{
    // Generate some random bytes and print them in hex
    int ret;
    uint8_t buf[20];
    size_t i;

    ret = randombytes(&buf[0], sizeof(buf));
    if (ret != 0) {
        printf("Error in `randombytes`");
        return 1;
    }    
    for (i = 0; i < sizeof(buf); ++i) {
        printf("%02hhx", buf[i]);
    }
    printf("\n");
    return 0;
}

How secure is it really?

While building this I keep one rule of thumb which is: Trust the OS. Most OS'es implement a secure random generator, which is seeded by a good entropy source. We will always use this random source. This essentially means that the implementation is highly platform-dependent. For example we use getrandom on Linux and arc4random on BSD systems.

What if the OS's random generator is bad?

If you are dealing with an OS that has a compromised random generator you are out of luck. The reason why you cannot generate high quality random data from userspace is that userspace is made so that everything is too deterministic. A secure random generator needs a good source of entropy, such as 2.4 GHz noise or the user's mouse movements. Collecting these kinds of events only works well when working on the lowest level.

Questions

It does not compile on my platform!

Please open an issue. If possible I will try to make a randombytes implementation for your platform.

Do you have bindings for language x?

No, your language probably already has a random source. Use that one.

Other

Feel free to send me an email on my Github associated e-mail address.

randombytes's People

Contributors

bfabiszewski avatar dsprenkels avatar jaromil avatar john-sharratt avatar joostrijneveld avatar mariaschopp avatar niekbouman avatar peterwilli avatar scurest avatar thijsmie avatar thomwiggers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

randombytes's Issues

urandom is never closed

Hi Daan, I found a little issue here:

fd = open("/dev/urandom", O_RDONLY);

/dev/urandom is opened at each call of the randombytes_linux_randombytes_urandom() but never closed.
I would suggest ether:

  • close at the exit of the function
  • use for fd a static variable initialized to -1 test it and if equal to -1 open the device and assign the descriptor to fd

the last could save some time if the function is called repeatedly

Add more macro guarding for Windows

In #43, @raidenluikang requests that more macro guarding should be added on windows.

And add more macro for detection Windows, for ex., boost predef uses these macros:

_WIN32
_WIN64
__WIN32__
__TOS_WIN__
__WINDOWS__

@raidenluikang Can you elaborate why this is necessary? Is the current state broken in any way?

Add functional test for old linux versions

Old linux versions do not have the getrandom system call. On these versions, randombytes.c falls back to using /dev/{u,}random for randomness. We should see whether GitHub actions has support for old versions of linux (probably not); or alternatively, hack the tests in such a way that the tests use the compatibility mode nonetheless. (See also #40)

Avoid getrandom or syscall(SYS_getrandom) in Android __ANDROID_API__ < 28

Android Os older than Android 9.0 (API_LEVEL = 28) broken syscall(SYS_getrandom).

Please, avoid it when building with NDK. Add something like

....
#elif defined(__linux__) || defined(__GNU__) || defined(GNU_KFREEBSD)

//---------- ADD THESE CODE --------------
#if defined(SYS_getrandom) && ((!defined(__ANDROID__) || __ANDROID_API__ >= 28)
       // use getrandom
       return randombytes_linux_randombytes_getrandom(buf, n);
#else 
    // use  /dev/urandom 
     return randombytes_linux_randombytes_urandom(buf, n);
 #endif
 //---------------------------------------
 #elif defined(BSD) ....

Forcing /dev/{u}random on Linux, or a runtime fallback for getrandom()

I think it would be useful to be able to build one binary and run it on Linux machines with and without getrandom() support.

One option is to add a compile time flag, so that you can build for /dev/{u}random even though the compiling machine has getrandom(). See https://github.com/niblo/randombytes/tree/use-devrandom for a quick attempt. The downside is that it would of course not use getrandom() even when it's supported.

Another alternative is to add runtime support for detecting getrandom(), and fall back to /dev/{u}random if it cannot detect it. Here's a sketch:

#define _GNU_SOURCE
#include <stdlib.h>
#include <dlfcn.h>

ssize_t (*getrandom)(void *, size_t, unsigned);

int main()
{
  getrandom = dlsym(RTLD_DEFAULT, "getrandom");  /* non-NULL if available */
}

The upside is that the getrandom() symbol does not have to be defined.

It doesn't guarantee that getrandom is available, only that it's defined in libc, but I think the same assumption is made already in randombytes_linux_randombytes_getrandom.

I would be interested in implementing something to this effect.

Binaries compiled using /dev/urandom on linux go into endless loop on joyent lx zones.

I compiled a binary on linux, it used the /dev/urandom device.

lib/randombytes/randombytes.c: In function 'randombytes':
lib/randombytes/randombytes.c:235:11: note: #pragma message: Using /dev/urandom device
 #  pragma message("Using /dev/urandom device")

Relevant strace lines from joyent lx zone.

open("/dev/urandom", O_RDONLY)          = 3
ioctl(3, RNDGETENTCNT, 0x7fffffefdf10)  = -1 ENOTTY (Inappropriate ioctl for device)
open("/dev/random", O_RDONLY)           = 4
poll([{fd=4, events=POLLIN}], 1, -1)    = 1 ([{fd=4, revents=POLLIN}])
ioctl(3, RNDGETENTCNT, 0x7fffffefdf0c)  = -1 ENOTTY (Inappropriate ioctl for device)
poll([{fd=4, events=POLLIN}], 1, -1)    = 1 ([{fd=4, revents=POLLIN}])
ioctl(3, RNDGETENTCNT, 0x7fffffefdf0c)  = -1 ENOTTY (Inappropriate ioctl for device)
poll([{fd=4, events=POLLIN}], 1, -1)    = 1 ([{fd=4, revents=POLLIN}])
ioctl(3, RNDGETENTCNT, 0x7fffffefdf0c)  = -1 ENOTTY (Inappropriate ioctl for device)
poll([{fd=4, events=POLLIN}], 1, -1)    = 1 ([{fd=4, revents=POLLIN}])
ioctl(3, RNDGETENTCNT, 0x7fffffefdf0c)  = -1 ENOTTY (Inappropriate ioctl for device)

It will continue polling forever.

The issue appears to be here,

randombytes_linux_get_entropy_avail(device) < bits);

I think this could be avoided by checking the return value after the call to randombytes_linux_get_entropy_avail() .

Add BCryptGenRandom for WINVER >= 0x0600

For Windows Vista and newer versions available bcrypt.h and BCryptGenRandom - which recommend in newer os.

Could add it ?

And add more macro for detection Windows, for ex., boost predef uses these macros:

_WIN32
_WIN64
__WIN32__
__TOS_WIN__
__WINDOWS__

Compilation fails when using musl

@jaromil gets compilation errors when compiling with the musl libc:

randombytes.c: In function ‘randombytes_linux_get_entropy_avail’:
randombytes.c:134:12: error: ‘RNDGETENTCNT’ undeclared (first use in this function)
  ioctl(fd, RNDGETENTCNT, &ret);
            ^
randombytes.c:134:12: note: each undeclared identifier is reported only once for each function it appears in

Note that compilation also fails on getrandom, because linux/random.h cannot be found (header file redundant, because of sys/syscall.h?).

  • Musl does not seem to be able to import linux symbols (because of portability issues). They say they will support getrandom() (not SYS_getrandom) here: http://www.openwall.com/lists/musl/2017/09/28/8. But in my case musl (1.1.19-1) hasn't yet added support.

  • In these cases we should indeed fall back to using /dev/urandom. But RNDGETENTCNT is (probably) glib-specific. I hesitate to skip the entropy test. Maybe see what libsodium does here.

  • getrandom syscall fix

  • /dev/urandom fix

randombytes is not support on this plateform

Hi, I write a tiny kernel , I want to port this libs , I don't provide /dev/urandom . Could you help me to implement a randmombytes which does not keep any dependence on OS ? thanks very much.

Tracking issue: test suite

Still to do:

  • Create functional tests (call randombytes twice, check if output differs)
  • Write a mocking test suite (using cmocka a home-brewed mocking framework)

Platforms:

  • windows: use Appveyor (only builds)
  • linux<3.17 (/dev/urandom): use Travis
  • linux>=3.17 (getrandom): use Travis?
  • osx: use Travis
  • bsd: ??
  • node: Use Travis (d4a32f8)

Original report:

Hi there again :^) thanks for sharing this pretty clean and handy implementation. Have you thought of adding a test suite that helps measuring the entropy on each system it is ran? This library may be of help https://github.com/dyne/libdisorder

Fix nodejs ci tests

The ci tests for #30 error on a couple of nodejs platforms, because docker hub has started rate-limiting downloads of docker images.

Add functional test for windows

We are currently only testing the build for windows. We are not testing the functionality of randombytes.c on windows. We should add this to the CI pipeline. (See also #40)

Support Electron apps

crypto = require('crypto');

The code under randombytes_js_randombytes_nodejs doesn't seem to work for Electron apps webassembly. Since many implementations don't check for return value of randombytes, downstream code was silently passing and causing security issues.

We have an updated version for randombytes_js_randombytes_nodejs that worked for electronjs app as well (as per Mozilla docs, window.crypto is a CSPRNG)
https://developer.mozilla.org/en-US/docs/Web/API/Crypto

Example:
https://github.com/DogeProtocol/hybrid-pqc/blob/d13f9d3944515ccdd7eee4fe98b08562b71564ef/random/randombytes.c#L322C1-L327C4

`#if defined(EMSCRIPTEN)
static int randombytes_js_randombytes_nodejs(void *buf, size_t n) {

const int ret = EM_ASM_INT({

	if (window.crypto && window.crypto.getRandomValues) { 
		var randBuffer = new Uint8Array($1);
		window.crypto.getRandomValues(randBuffer);
		writeArrayToMemory(randBuffer, $0);
		return 0;
	}


	var cryptoMod;
	try {
		cryptoMod = require('crypto');
	} catch (error) {
		return -2;
	}
	try {
		writeArrayToMemory(cryptoMod.randomBytes($1), $0);
		return 0;
	} catch (error) {
		return -1;
	}
}, buf, n);
switch (ret) {
case 0:
	return 0;
case -1:
	errno = EINVAL;
	return -1;
case -2:
	errno = ENOSYS;
	return -1;
}
return -3;
assert(false); // Unreachable

}
#endif /* defined(EMSCRIPTEN) */`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.