-
Notifications
You must be signed in to change notification settings - Fork 8k
[WIP] Easy User-land CSPRNG #1119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
f8d7aec
26e4ed2
3c5fcac
e96b077
aa0ca69
b32e0d0
2c659ed
a1e6229
bbc9198
7a99db6
3d413ad
513d5c9
77f99cc
7ef5754
766ce0c
99e36d6
c6fc391
ab02b7b
fd0570b
7ae4917
a67e42f
f8a6d38
2990341
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| /* | ||
| +----------------------------------------------------------------------+ | ||
| | PHP Version 7 | | ||
| +----------------------------------------------------------------------+ | ||
| | Copyright (c) 1997-2015 The PHP Group | | ||
| +----------------------------------------------------------------------+ | ||
| | This source file is subject to version 3.01 of the PHP license, | | ||
| | that is bundled with this package in the file LICENSE, and is | | ||
| | available through the world-wide-web at the following url: | | ||
| | http://www.php.net/license/3_01.txt | | ||
| | If you did not receive a copy of the PHP license and are unable to | | ||
| | obtain it through the world-wide-web, please send a note to | | ||
| | license@php.net so we can mail you a copy immediately. | | ||
| +----------------------------------------------------------------------+ | ||
| | Authors: Sammy Kaye Powers <me@sammyk.me> | | ||
| +----------------------------------------------------------------------+ | ||
| */ | ||
|
|
||
| /* $Id$ */ | ||
|
|
||
| #ifndef PHP_RANDOM_H | ||
| #define PHP_RANDOM_H | ||
|
|
||
| PHP_FUNCTION(random_bytes); | ||
| PHP_FUNCTION(random_hex); | ||
| PHP_FUNCTION(random_int); | ||
| #endif | ||
|
|
||
| /* | ||
| * Local variables: | ||
| * tab-width: 4 | ||
| * c-basic-offset: 4 | ||
| * End: | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| /* | ||
| +----------------------------------------------------------------------+ | ||
| | PHP Version 7 | | ||
| +----------------------------------------------------------------------+ | ||
| | Copyright (c) 1997-2015 The PHP Group | | ||
| +----------------------------------------------------------------------+ | ||
| | This source file is subject to version 3.01 of the PHP license, | | ||
| | that is bundled with this package in the file LICENSE, and is | | ||
| | available through the world-wide-web at the following url: | | ||
| | http://www.php.net/license/3_01.txt | | ||
| | If you did not receive a copy of the PHP license and are unable to | | ||
| | obtain it through the world-wide-web, please send a note to | | ||
| | license@php.net so we can mail you a copy immediately. | | ||
| +----------------------------------------------------------------------+ | ||
| | Authors: Sammy Kaye Powers <me@sammyk.me> | | ||
| +----------------------------------------------------------------------+ | ||
| */ | ||
|
|
||
| /* $Id$ */ | ||
|
|
||
| #include <stdlib.h> | ||
|
|
||
| #include "php.h" | ||
|
|
||
| // Copy/pasted from string.c | ||
| static char hexconvtab[] = "0123456789abcdef"; | ||
|
|
||
| // Copy/pasted from string.c | ||
| static zend_string *php_bin_to_hex(const unsigned char *old, const size_t oldlen) | ||
| { | ||
| zend_string *result; | ||
| size_t i, j; | ||
|
|
||
| result = zend_string_safe_alloc(oldlen, 2 * sizeof(char), 0, 0); | ||
|
|
||
| for (i = j = 0; i < oldlen; i++) { | ||
| result->val[j++] = hexconvtab[old[i] >> 4]; | ||
| result->val[j++] = hexconvtab[old[i] & 15]; | ||
| } | ||
| result->val[j] = '\0'; | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| static int *php_random_bytes(zend_string *bytes, size_t length) | ||
| { | ||
| FILE *fp; | ||
|
|
||
| #ifdef PHP_WIN32 | ||
| // @todo Need to add Windows support | ||
| fp = NULL; | ||
| #else | ||
| fp = fopen("/dev/urandom" , "rb"); | ||
| #endif | ||
|
|
||
| if (fp == NULL) { | ||
| php_error_docref(NULL, E_WARNING, "Unable to open /dev/urandom"); | ||
| return FAILURE; | ||
| } | ||
|
|
||
| // @todo I think this has to be char & int! | ||
| if (fgets(bytes, 10, fp) == NULL) { | ||
| fclose(fp); | ||
| php_error_docref(NULL, E_WARNING, "Unable to read from /dev/urandom"); | ||
| return FAILURE; | ||
| } | ||
| fclose(fp); | ||
|
|
||
| return bytes; | ||
| } | ||
|
|
||
| /* {{{ proto string random_bytes(int bytes) | ||
| Return an arbitrary length of pseudo-random bytes as binary string */ | ||
| PHP_FUNCTION(random_bytes) | ||
| { | ||
| size_t length; | ||
| zend_string *bytes; | ||
|
|
||
| int argc = ZEND_NUM_ARGS(); | ||
|
|
||
| if (argc != 0) { | ||
| if (zend_parse_parameters(argc, "l", &length) == FAILURE) { | ||
| return; | ||
| } else if (length <= 0) { | ||
| php_error_docref(NULL, E_WARNING, "length(" ZEND_LONG_FMT ") must be greater than 0", length); | ||
| RETURN_FALSE; | ||
| } | ||
| } | ||
|
|
||
| if (php_random_bytes(bytes, length) == FAILURE) { | ||
| return; | ||
| } | ||
|
|
||
| RETURN_STR(bytes); | ||
| } | ||
| /* }}} */ | ||
|
|
||
| /* {{{ proto string random_hex(int bytes) | ||
| Return an arbitrary length of pseudo-random bytes as hexadecimal string */ | ||
| PHP_FUNCTION(random_hex) | ||
| { | ||
| size_t length; | ||
| zend_string *bytes; | ||
| zend_string *hex; | ||
|
|
||
| int argc = ZEND_NUM_ARGS(); | ||
|
|
||
| if (argc != 0) { | ||
| if (zend_parse_parameters(argc, "l", &length) == FAILURE) { | ||
| return; | ||
| } else if (length <= 0) { | ||
| php_error_docref(NULL, E_WARNING, "length(" ZEND_LONG_FMT ") must be greater than 0", length); | ||
| RETURN_FALSE; | ||
| } | ||
| } | ||
|
|
||
| if (php_random_bytes(bytes, length) == FAILURE) { | ||
| return; | ||
| } | ||
|
|
||
| hex = php_bin_to_hex(bytes, length); | ||
|
|
||
| RETURN_STR(hex); | ||
| } | ||
| /* }}} */ | ||
|
|
||
| /* {{{ proto int random_int(int min, int max) | ||
| Return an arbitrary pseudo-random integer */ | ||
| PHP_FUNCTION(random_int) | ||
| { | ||
| zend_long min; | ||
| zend_long max; | ||
| zend_long number; | ||
| int argc = ZEND_NUM_ARGS(); | ||
|
|
||
| if (argc != 0) { | ||
| if (zend_parse_parameters(argc, "ll", &min, &max) == FAILURE) { | ||
| return; | ||
| } else if (max < min) { | ||
| php_error_docref(NULL, E_WARNING, "max(" ZEND_LONG_FMT ") is smaller than min(" ZEND_LONG_FMT ")", max, min); | ||
| RETURN_FALSE; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the
Naturally I understand that the likelihood of these characteristics causing problems in PHP applications is small but I think reviewers should be aware of it.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nikic That looks correct.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't we just use the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @datibbaw Because RAND_RANGE is highly biased. It's not an option for crypto-quality randomness. I'm not aware of algorithms for this that don't use a form of rejection sampling.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Get out! :) In
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, that's fair enough; I shall read more into this, thanks :) |
||
| } | ||
|
|
||
| number = min + max; | ||
|
|
||
| RETURN_LONG(number); | ||
| } | ||
| /* }}} */ | ||
|
|
||
| /* | ||
| * Local variables: | ||
| * tab-width: 4 | ||
| * c-basic-offset: 4 | ||
| * End: | ||
| * vim600: sw=4 ts=4 fdm=marker | ||
| * vim<600: sw=4 ts=4 | ||
| */ | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably that should be
RETURN_FALSEas well? Same inrandom_int.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! I'll fix.