4

I'm getting hexadecimal digits to generate unique random activators link, such as:

hostname/account/confirm/$randomHex

By searching, actually, my random hex using PHP could be:

bin2hex( openssl_random_pseudo_bytes(16) )

Above generates a string with 32 hex digits and i would appreciate to use a less length as 12 hex digits.

Considering the power processing of computers, what's the more secure minimum size of the hexadecimal that i'm able to use?

Scott Arciszewski
  • 33,610
  • 16
  • 89
  • 206
Alexandre Thebaldi
  • 4,546
  • 6
  • 41
  • 55
  • imo, As you are doing, generate the 16 byte random number and then `base64url_encode` them. For the functions see [Url safe base64 encoding and decoding in PHP](http://www.katcode.com/url-safe-base64-encoding-in-php/), Also: ['base64url' variant encoding](http://php.net/manual/en/function.base64-encode.php#103849). These are safe to use everywhere and secure – Ryan Vincent Aug 22 '15 at 12:07
  • Use [`Random::hexLowercaseString(12)`](https://github.com/delight-im/PHP-Random) (48 bits) or [`Random::alphanumericString(12)`](https://github.com/delight-im/PHP-Random) (71 bits). – caw Nov 20 '19 at 16:46

2 Answers2

2

Considering the power processing of computers, what's the more secure minimum size of the hexadecimal that i'm able to use?

This is actually an easy number to calculate, if you have a threat model in place.

Based on the URL you provided, it seems you're generating a URL for email ownership verification. This is decidedly needy than, say, a password reset URL.

If you rate limit bad attempts (i.e. block their IP address from being able to attempt again for 24 hours), you can get by with 8 hex characters (32 bits) sheer chance means they'll be able to guess a valid confirmation link after 65,536 tries with 50% probability. (The Birthday paradox.) Pulling this off would also require 65,536 IP addresses just to blindly confirm someone's email address (probably not their own).

HOWEVER!

As stated above, if you are using this for, e.g. a recovery feature (I forgot my password), don't skimp out on string length. 128 bits (32 hex, 16 raw binary) should be considered a lower bound. I'd say shoot for 256 bits just to be safe.

Above generates a string with 32 hex digits and i would appreciate to use a less length as 12 hex digits.

If you want to increase the security of a string given a fixed length, the only way to do so is to increase the number of possible values for each character in the string.

Even if you were using raw binary, which you're not, the upper limit of 11 characters is 88 bits of entropy. Specifying hex cuts you down to 44 (but most likely 40, since you'd probably write bin2hex(random_bytes(5)) here).

If you want to securely generate an fixed-size string with an arbitrary alphabet, check out this StackOverflow answer.

Community
  • 1
  • 1
Scott Arciszewski
  • 33,610
  • 16
  • 89
  • 206
2

16 randomly generated bytes gives 128bits of entropy. A key with 128bits of entropy is uncrackable using an offline brute force attack. Even with every computer in the world working on cracking it.

However, you are looking to prevent an online brute force attack, which is much slower. If you wanted 12 hex characters, this would be 6 bytes and therefore 48 bits of entropy. This gives you 281,474,976,710,656 possibilities. If your site takes 0.25* seconds to respond, this would take 2^47 * 0.25 = 35,184,372,088,832 seconds to brute force on average by making requests to your site (1.116 million years).

You're safe with 48 bits.

*In reality this would be a parallel attack, so the attacker would not have to wait for a response if all they're trying to do is validate an account. However, there will be a rate limit to any system, slowing the attack. Adjust the figures to suit your system as necessary.

Community
  • 1
  • 1
SilverlightFox
  • 32,436
  • 11
  • 76
  • 145