PHP RFC: Improve uniqid() uniqueness
- Version: 0.9
- Date Created: 2016-09-12
- Date Modified: 2016-09-12
- Author: Yasuo Ohgaki yohgaki@ohgaki.net
- Status: Inactive
- First Published at: http://wiki.php.net/rfc/uniqid
Introduction
uniqid() is supposed to create unique ID based on time. Current implementation does not make sure uniqueness of result because it relies on system time.
Why it is not unique
Current implementation uses usleep(1) to generate unique ID based on microtime(). Most systems adjust system time by NTP or similar. System time is adjusted by magnitude of milliseconds or even seconds constantly. Therefore, usleep(1) does not guarantee uniqueness of return value on the same process/thread nor other process/thread.
Poor entropy source
Current implementation uses php_combined_lcd() and 9 digits float value as “more entropy”. php_combined_lcg() is weak source of entropy. Since we have php_random_bytes() as better entropy source, it is preferred to use stronger entropy source.
- Current entropy range: About 1 billion
- Proposed entropy range: 2^50 or more. About 1048567 billions.
Proposal
- Change “more_entropy” option to int parameter to specify number of entropy chars.
- Enable “more entropy” option by default.
- Use php_random_bytes() as entropy source.
string uniqid([string $prefix [, int $number_of_entropy_chars ]]);
Where $number_of_entropy_chars are:
- 0 for disable more entropy. (Compatible with current $more_entropy=FALSE)
- 1 for 10 digits entropy. (Compatible with current $more_entropy=TRUE. About 30 bits entropy)
- 13 to 255 for number of entropy [0-v]{13,255} chars. (13 chars = 65 bits entropy)
Note on usage
Users should never use uniqid() for any crypt related purposes even with this change. uniqid() does not provide crypt secure random value. Users should use random_bytes() for crypt purposes.
Note on performance
usleep(1) is not used when “more entropy” is used. Therefore, default behavior is about 25x faster.
Note on uniqueness
Although it is unlikely, uniqueness is _not_ guaranteed even with this proposal, but this proposal improves uniqueness a lot. This nature will be documented in the manual.
Discussions
User shouldn't use uniqid(). uniqid() should be deprecated
It provides good enough unique ID and many users use uniqid() for test scripts. We don't have to deprecate it.
This gives false sense of security
It mitigates risks of misuses, but users should not misunderstand new uniqid() generates crypt secure random values.
Backward Incompatible Changes
Almost all uniqid() usages do not care about return value chars nor length. Therefore, BC will be minimum.
Windows CYGWIN environment requires “more entropy” always and default “more entropy” optione for CYGWIN is TRUE by default. It raises E_WARNING when “more entropy” option is FALSE.
Default return value length
- Return value is longer than current default. (13 -> 23 chars)
Current implementation output example:
$ php -r 'var_dump(uniqid(), uniqid("", TRUE));' string(13) "57d60ed86d339" string(23) "57d60ed86d33c9.09289803"
Chars used by "more entropy"
- More entropy uses digits and alphabets.
Proposed implementation output example:
$ ./php-bin -r 'var_dump(uniqid("", FALSE), uniqid("", TRUE));' string(13) "57d60f6bc6637" string(23) "57d60f6bc6654mb7167bnou"
Proposed PHP Version(s)
Next PHP (Currently PHP 7.2)
RFC Impact
To SAPIs
None.
To Existing Extensions
None.
To Opcache
None.
New Constants
None.
php.ini Defaults
N/A
Open Issues
Make sure there are no open issues when the vote starts!
Unaffected PHP Functionality
Anything but uniqid() is affected.
Future Scope
None.
Proposed Voting Choices
State whether this project requires a 2/3 majority (see voting)
Patches and Tests
Implementation
After the project is implemented, this section should contain
- the version(s) it was merged to
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
References
Links to external references, discussions or RFCs
Rejected Features
Keep this updated with features that were discussed on the mail lists.
ChangeLog
- Made 2nd parameter a int