Bad random session ids due to bad Rand::random randomness
Closed this issue · 7 comments
I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:
Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101
As you can see, there is a call to the function random(32)
, which promises to deliver 32 random characters.
That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).
Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).
Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min
and $max
, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.
And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes()
would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand()
would only issue 31 bits of randomness.
All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).
Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */
= 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)
What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84
Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv()
, openssl_random_pseudo_bytes()
, fopen('/dev/urandom', 'r')
- and only then, as a last resort, mt_rand()
with as many calls as there should be bytes in the salt string.
Keep in mind that randomness comes with entropy, and it is hardly retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In case they are not, we are using openssl function (if available) that has 64 bits, which is definitely enough for any case.
The bits of randomness are not in par with bits of cryptography strength, and don't need to be. They just need to be unguessable!
-A
Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.com
On Sep 17, 2013, at 4:16 PM, SvenRtbg notifications@github.com wrote:
I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:
Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101
As you can see, there is a call to the function random(32), which promises to deliver 32 random characters.
That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).
Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).
Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min and $max, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.
And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes() would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand() would only issue 31 bits of randomness.
All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).
Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)
What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84
Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(), fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand() with as many calls as there should be bytes in the salt string.—
Reply to this email directly or view it on GitHub.
If the basic randomness can only generate 31 bits of different values,
the result is very easy to bruteforce.
Even though the hashing hides that very poor randomness, you will still
only generate 4294967295 different values.
Compare that to the possible 1,3407807929942597099574024998206e+154
values of a SHA512...
Another reference, which is talking about the cracking of 56-bit keys
within 250 days in 2006:
http://www.codinghorror.com/blog/2006/07/brute-force-key-attacks-are-for-dummies.html
I am a little bit concerned about your answer here. 31 bits of
randomness is WAY TOO FEW! In fact, it is a worthy target to brute-force
it. Using 100 requests in parallel, each taking 100ms, it will only take
50 days to scan the whole session id space.
Am 17.09.2013 23:29, schrieb AbiusX:
Keep in mind that randomness comes with entropy, and it is hardly retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In case they are not, we are using openssl function (if available) that has 64 bits, which is definitely enough for any case.The bits of randomness are not in par with bits of cryptography strength, and don't need to be. They just need to be unguessable!
-A
Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.comOn Sep 17, 2013, at 4:16 PM, SvenRtbg notifications@github.com wrote:
I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:
Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101
As you can see, there is a call to the function random(32), which promises to deliver 32 random characters.
That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).
Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).
Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min and $max, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.
And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes() would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand() would only issue 31 bits of randomness.
All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).
Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)
What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84
Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(), fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand() with as many calls as there should be bytes in the salt string.—
Reply to this email directly or view it on GitHub.
Reply to this email directly or view it on GitHub:
#69 (comment)
Well you need to bruteforce a weak randomness on the server, not on your own supercomputer :D That is the difference.
-A
Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.com
On Sep 17, 2013, at 5:43 PM, SvenRtbg notifications@github.com wrote:
If the basic randomness can only generate 31 bits of different values,
the result is very easy to bruteforce.Even though the hashing hides that very poor randomness, you will still
only generate 4294967295 different values.Compare that to the possible 1,3407807929942597099574024998206e+154
values of a SHA512...Another reference, which is talking about the cracking of 56-bit keys
within 250 days in 2006:
http://www.codinghorror.com/blog/2006/07/brute-force-key-attacks-are-for-dummies.htmlI am a little bit concerned about your answer here. 31 bits of
randomness is WAY TOO FEW! In fact, it is a worthy target to brute-force
it. Using 100 requests in parallel, each taking 100ms, it will only take
50 days to scan the whole session id space.Am 17.09.2013 23:29, schrieb AbiusX:
Keep in mind that randomness comes with entropy, and it is hardly retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In case they are not, we are using openssl function (if available) that has 64 bits, which is definitely enough for any case.The bits of randomness are not in par with bits of cryptography strength, and don't need to be. They just need to be unguessable!
-A
Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.comOn Sep 17, 2013, at 4:16 PM, SvenRtbg notifications@github.com wrote:
I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:
Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101
As you can see, there is a call to the function random(32), which promises to deliver 32 random characters.
That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).
Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).
Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min and $max, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.
And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes() would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand() would only issue 31 bits of randomness.
All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).
Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)
What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84
Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(), fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand() with as many calls as there should be bytes in the salt string.—
Reply to this email directly or view it on GitHub.
Reply to this email directly or view it on GitHub:
#69 (comment)—
Reply to this email directly or view it on GitHub.
So what would be lost if we would actually use some maximum amount of
available random bits (e.g. 64 random bytes) instead of the current
limited randomess of 4 bytes?
Am 17.09.2013 23:44, schrieb AbiusX:
Well you need to bruteforce a weak randomness on the server, not on your own supercomputer :D That is the difference.
-A
Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.comOn Sep 17, 2013, at 5:43 PM, SvenRtbg notifications@github.com wrote:
If the basic randomness can only generate 31 bits of different values,
the result is very easy to bruteforce.Even though the hashing hides that very poor randomness, you will still
only generate 4294967295 different values.Compare that to the possible 1,3407807929942597099574024998206e+154
values of a SHA512...Another reference, which is talking about the cracking of 56-bit keys
within 250 days in 2006:
http://www.codinghorror.com/blog/2006/07/brute-force-key-attacks-are-for-dummies.htmlI am a little bit concerned about your answer here. 31 bits of
randomness is WAY TOO FEW! In fact, it is a worthy target to brute-force
it. Using 100 requests in parallel, each taking 100ms, it will only take
50 days to scan the whole session id space.Am 17.09.2013 23:29, schrieb AbiusX:
Keep in mind that randomness comes with entropy, and it is hardly retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In case they are not, we are using openssl function (if available) that has 64 bits, which is definitely enough for any case.The bits of randomness are not in par with bits of cryptography strength, and don't need to be. They just need to be unguessable!
-A
Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.comOn Sep 17, 2013, at 4:16 PM, SvenRtbg notifications@github.com wrote:
I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:
Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101
As you can see, there is a call to the function random(32), which promises to deliver 32 random characters.
That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).
Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).
Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min and $max, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.
And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes() would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand() would only issue 31 bits of randomness.
All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).
Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)
What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84
Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(), fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand() with as many calls as there should be bytes in the salt string.—
Reply to this email directly or view it on GitHub.
Reply to this email directly or view it on GitHub:
#69 (comment)—
Reply to this email directly or view it on GitHub.
Reply to this email directly or view it on GitHub:
#69 (comment)
Hello Sven,
I get your point... (though I did not understood all of it ... like "SHA512
itself is 128 hex chars long, leaving room for 64 bytes of randomness
instead of only 4 bytes"...what does this means ? )..
Now the test cases you sent obviously fails and proves the point...so
here's what we can do (any one of them):
-
we can remove all the codes from the random library and replace it
with mcrypt_create_iv()
OR openssl_random_pseudo_bytes()... -
we can remove the capping of 31 bits and increase it to say 64
bits...then we can increase the random bits needed in openssl function from
4 to say 46...and then replace the call to mt_rand with as
many occurrences as bytes needed. -
I dont know if this will work, but for a given length, if the length is
greater than 32, then we can call the random function as many times until
we get the whole string as required by the developer. i.e if the
requirement is of 1024 bytes, then we can call the random function 1024/32
times and then concatenate each of the result to produce a 1024 character
random string.
On Tue, Sep 17, 2013 at 5:46 PM, SvenRtbg notifications@github.com wrote:
So what would be lost if we would actually use some maximum amount of
available random bits (e.g. 64 random bytes) instead of the current
limited randomess of 4 bytes?Am 17.09.2013 23:44, schrieb AbiusX:
Well you need to bruteforce a weak randomness on the server, not on your
own supercomputer :D That is the difference.
-A
Notice: This message is digitally signed, its source and integrity are
verifiable.
If you mail client does not support S/MIME verification, it will display
a file (smime.p7s), which includes the X.509 certificate and the signature
body. Read more at Certified E-Mail with Comodo and Thunderbird in
AbiusX.comOn Sep 17, 2013, at 5:43 PM, SvenRtbg notifications@github.com wrote:
If the basic randomness can only generate 31 bits of different values,
the result is very easy to bruteforce.Even though the hashing hides that very poor randomness, you will still
only generate 4294967295 different values.Compare that to the possible 1,3407807929942597099574024998206e+154
values of a SHA512...Another reference, which is talking about the cracking of 56-bit keys
within 250 days in 2006:http://www.codinghorror.com/blog/2006/07/brute-force-key-attacks-are-for-dummies.html
I am a little bit concerned about your answer here. 31 bits of
randomness is WAY TOO FEW! In fact, it is a worthy target to brute-force
it. Using 100 requests in parallel, each taking 100ms, it will only take
50 days to scan the whole session id space.Am 17.09.2013 23:29, schrieb AbiusX:
Keep in mind that randomness comes with entropy, and it is hardly
retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of
randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In
case they are not, we are using openssl function (if available) that has 64
bits, which is definitely enough for any case.The bits of randomness are not in par with bits of cryptography
strength, and don't need to be. They just need to be unguessable!
-A
Notice: This message is digitally signed, its source and integrity are
verifiable.
If you mail client does not support S/MIME verification, it will
display a file (smime.p7s), which includes the X.509 certificate and the
signature body. Read more at Certified E-Mail with Comodo and Thunderbird
in AbiusX.comOn Sep 17, 2013, at 4:16 PM, SvenRtbg notifications@github.com
wrote:I think the was that session ids are generated is not very random.
And this is concealed because of a layer of function calls that all look
very good. Please follow me on the code path:Let's start at Session::newSession
https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101As you can see, there is a call to the function random(32), which
promises to deliver 32 random characters.That function
https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is
only a simple proxy and forwards the call to Rand::randStr(32).Now that function
https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109actually does something: It grabs some randomness, hashes it into a string
of finite length (which would lead to the whole functions so far to NOT
deliver e.g. a random string of 2048 characters without hint or error - bad
in itself, but not my point).Ok, randomness... We do see a call to Rand::randRange()
https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with
default parameters. This function does some checks, probably reverses $min
and $max, grabs some randomness and then simply scales that into the range
given. The range for default parameters is $min=0, $max = 2^31. So whatever
the random generator delivers, it will here be reduced to 31 bits of
randomness.And the random number generator is in Rand::random()
https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47itself has no parameters. In an ideal situation, the very good random
function openssl_random_pseudo_bytes() would be asked for FOUR bytes of
randomness, which equals 32 bits. In absence of this function, the very bad
random generator mt_rand() would only issue 31 bits of randomness.All in all, the session ids generated by this code will only contain
31 bits of randomness, packed into a nice looking substring of SHA512,
suggesting much more randomness being included (SHA512 itself is 128 hex
chars long, leaving room for 64 bytes of randomness instead of only 4
bytes).Even the PHP default session id hash has /* maximum 15+19+19+10 bytes
*/ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information -
and this is criticized as "attackable" by some. (see
https://github.com/php/php-src/blob/master/ext/session/session.c#L309)What are good sources of randomness? I think a good example is given
in the random salt generation of the password_hash library:
https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84Plenty of sources are being asked, in the hope to find some good
randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(),
fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand()
with as many calls as there should be bytes in the salt string.—
Reply to this email directly or view it on GitHub.
Reply to this email directly or view it on GitHub:
#69 (comment)—
Reply to this email directly or view it on GitHub.
Reply to this email directly or view it on GitHub:
#69 (comment)—
Reply to this email directly or view it on GitHubhttps://github.com//issues/69#issuecomment-24625266
.
Regards,
Rahul Chaudhary
Ph - 412-519-9634
SHA512 produces a hash string of 128 hex characters. On hex character represents 4 bits, so 128 hex characters are 64 bytes. So SHA512 can have the whole range of 64 bytes of different values - which is about 2^(64*8) or 2^512.
What to do? First, get a clear picture of what this function should return: Rand::randstr($length)
It sounds like "random string of length X" - what does this include?
- String length must be of the requested length. If I ask for one million characters, I must get them - or I must get an error stating that I was asking for too much, if there is a technical limit and I am only allowed to ask for a maximum of 1000 characters for example.
- How many different characters do I get at best? Technically, there are some options: a) Any byte from 0..255 b) only printable character bytes from 32..255 (excluding some at around 128..160) c) only hexadecimal characters "0".."9" + "a".."f"
For optimal randomness, the return string should contain as many different characters as possible. But it should also return a feasible selection of characters for a purpose like random password generation. But even if it will only output hex, this is fine, but should be taken into account by the developer using it, because he must then ask for more characters to get the same amount of possible different values.
Now the random generation: I'd really just copy the approach from the password API I linked. That part will actually produce any number of random characters - and if used directly by Rand::randstr
, would also eliminate the problem there, with the output being "any byte in the range 0..255".
Those links maybe useful
https://www.grc.com/js/uheprng.js
https://www.grc.com/otg/uheprng.htm