-
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 |
|---|---|---|
|
|
@@ -31,8 +31,6 @@ | |
|
|
||
| static int php_random_bytes(void *bytes, size_t size) | ||
| { | ||
| int n = 0; | ||
|
|
||
| #if PHP_WIN32 | ||
| /* Defer to CryptGenRandom on Windows */ | ||
| if (php_win32_get_random_bytes(bytes, size) == FAILURE) { | ||
|
|
@@ -57,6 +55,7 @@ static int php_random_bytes(void *bytes, size_t size) | |
| return FAILURE; | ||
| } | ||
|
|
||
| size_t n = 0; | ||
| while (read_bytes < size) { | ||
| n = read(fd, bytes + read_bytes, size - read_bytes); | ||
| if (n < 0) { | ||
|
|
@@ -96,7 +95,7 @@ PHP_FUNCTION(random_bytes) | |
|
|
||
| if (php_random_bytes(bytes->val, size) == FAILURE) { | ||
| zend_string_release(bytes); | ||
| return; | ||
| RETURN_FALSE; | ||
| } | ||
|
|
||
| bytes->val[size] = '\0'; | ||
|
|
@@ -132,7 +131,7 @@ PHP_FUNCTION(random_int) | |
| umax = max - min; | ||
|
Contributor
Author
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. We need to make sure 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. You're already checking this on line 126.
Contributor
Author
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. Oh snap. Not. Enough. Coffee! Oh wait, I'm drinking decaf for some reason today. :/ |
||
|
|
||
| if (php_random_bytes(&result, sizeof(result)) == FAILURE) { | ||
|
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. What is the principal difference of this move from casting some garbage into integer? Could someone point to a theory behind this?
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. What do you mean? How else would you do it?
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. Yeah, that was actually my question :) Maybe I'm too fixed on LCG, so just making a stab on finding some system. In a LCG one would have a seed and a kind of formula. Here, we read some sequence of bits which are then inclined to be an integer. Probably right, at the end those bits are glued together. At the end, the integer is in the exact range of how much bits was requested. But just wondering, no further shuffling, endianness difference, etc., just taking them as is? Are there some tests on the quality of the outcome? That's basically what I was asking. 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. @weltling There is no need. If the input to the algorithm is a sequence of independent, uniformly-distributed random bytes then the its output is guaranteed to be independent, uniformly-distributed over the requested range and have the same "kind" of randomness as the input. In this case, since we are using trusted sources of crypto-secure pseudo-random bytes, the output is a crypto-secure pseudo-random integer. Try thinking of it this way. Say you need random numbers in the range 0 to 13 and all you have as a source of randomness is a friend with a 20-sided die. The only way (that I know) to get the numbers you need without bias or skewing the distribution is to ask your friend to keep rolling the die until it gives a number in the desired range. Now, say you need numbers in the range 0 to 8. You can map two disjoint subsets of the die's 0 to 19 range to the desired range and this improves the algorithm's efficiency. I believe this is exactly analogous to how this algorithm is supposed to work. (I am making no comment about the correctness of the implementation.) It's an old algorithm we can trust.
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. @weltling There's no need for any extra work. If an integer occupies 64 bits of memory, and we use a random source to set every one of those bits, the result is a random integer with the same quality as the random source. Endianness does not matter since every byte is independently random. If the bytes are ordered AB they are equally random to being ordered BA. There are tools that can test the quality of the random output, but you'll literally be testing the underlying source. We're putting our faith in the Linux/Windows/BSD APIs here. If it turns out that these sources are in fact low quality, then civilisation itself will collapse :)
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.
Indeed. Find the ceiling under RAND_MAX where
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. @lt the world is concurrent enough to not to break because of whichever virtual RNG :) But ok, so the presumption of innocence is applied to the OS randomness sources. @tom-- yeah, maybe also an improvement could be to ask the friend to throw more than one die at once. Possibly it could reduce the whole circles count. However not sure how reliable it would be with this method (i mean how many uniform random data one can get at once), for LCG i can say it could be done with something like AVX/SSE vectorization capabilities. Here it's probably only to be spotted empirically. Thanks for the answers, guys. |
||
| return; | ||
| RETURN_FALSE; | ||
| } | ||
|
|
||
| // Special case where no modulus is required | ||
|
|
||
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.
nmust be signed. It can beintorssize_t, but it needs to be signed. Otherwise theif (n < 0)condition can literally never happen.