#50996 [NEW]: crypt function incorrectly describes how to use MD5/Blowfish

From: Date: Wed, 10 Feb 2010 17:26:41 +0000
Subject: #50996 [NEW]: crypt function incorrectly describes how to use MD5/Blowfish
Groups: php.doc.bugs 
Request: Send a blank email to doc-bugs+get-3860@lists.php.net to get a copy of this message
From: cscott at ggot dot org Operating system: Irrelevant PHP version: 5.3.1 PHP Bug Type: Documentation problem Bug description: crypt function incorrectly describes how to use MD5/Blowfish Description: ------------ The documentation provided at http://php.net/crypt is extremely weak and sometimes inaccurate. At the bottom there is a note to check your Unix man pages for more info, which would probably have been a perfectly acceptable response, were it not for the face that PHP added support for certain algorithms even if they were not present in the system's library, making this a universal PHP issue now instead of just a system/dependency issue. I suggest the following (or something like it) be added to the PHP Manual with respect to the crypt function in order to make this valuable function and the changes made to its support more accessible. Additional text that applies to all, and is implied but not made clear: ---- Since all salts are considered to have a fixed, maximum length, the result of a call to crypt() may be passed to subsequent calls to crypt() in the salt parameter as a method of ensuring the same salt is used for validation purposes. Example: crypt(p, crypt(p, s)) == crypt(p, s) ---- Current, Erroneous (or at least misleading) text: ---- CRYPT_MD5 - MD5 encryption with a twelve character salt starting with $1$ CRYPT_BLOWFISH - Blowfish encryption with a sixteen character salt starting with $2$ or $2a$ At least on Windows systems, which probably means we're using the built in PHP support for these two algorithms, they follow these rules: CRYPT_MD5 - The salt follows this convention: '$1$SALTsalt$'; only the first 8 characters of any given salt will be considered, so hashes produced with the salt '$1$SALTsalt$' will be identical to ones produced with a salt such as '$1$SALTsaltSALTsalt$'. [[Note: I originally thought this was because the string was being treated as a base64 entity with a custom alphabet, but testing reveals that any characters are valid in the salt of this algorithm]] CRYPT_BLOWFISH - Salts are interpreted as, and hashes returned as, a base64 string; this string is based on the GNU C Library's base64 alphabet for crypt (found here: http://www.gnu.org/s/libc/manual/html_node/crypt.html) but otherwise follows standard conventions of any base64 string. The '$' character is considered a null, or padding character. The salt follows this convention '$2a$##$SALTsaltSALTsaltSALTsa'; The beginning may of course be '$2$' or '$2a$'. The next three characters should be a decimal number indicating how many times the key should be calculated (i.e., how expensive it is to calculate the key). This number will be interpreted as a power of two (e.g., $2a$07$ would be interpreted as 2^7), and cannot be less than 3 or greater than 31 [[Note: have not tested this on a 64-bit system, so it might be higher]]. The salt is composed of up to 22 characters from an alphabet ./0-9A- Za-z with the $ symbol considered a null/end-of-string character. Salts longer than 22 characters will only have the first 22 characters of the salt considered, while salts shorter than 22 characters will be padded with the '$' character, though this has no effect. Additionally, any part of the salt following a '$' character will not be considered (as processing of the salt will have terminated upon first encounter of '$'). Any characters which are not a part of the above alphabet and occur before a string-termination character ('$') will cause crypt to fail, returning and empty string. WARNING:{ Because the salt is interpreted as a base64 number, certain salts may potentially produce identical results. This occurs when two salts are identical except for one character the second salt that does not exist in the first (e.g., 'abcd' and 'abcde'), and the shorter of the two has a length divisible evenly by 4 (that is, Length Modulo 4 == 0). This happens because a base64 string is interpreted 4 bytes at a time, each byte representing 6 bits in the target string, and meaning that 1 byte requires at least two base64 characters to represent it. Because of this, the last character will not be interpreted as part of the salt, causing the identical hashes to be produced. In general, you should never use a salt that is shorter than the maximum allowed. } ---- -- Edit bug report at http://bugs.php.net/?id=50996&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=50996&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=50996&r=trysnapshot53 Try a snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=50996&r=trysnapshot60 Fixed in SVN: http://bugs.php.net/fix.php?id=50996&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=50996&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=50996&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=50996&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=50996&r=needscript Try newer version: http://bugs.php.net/fix.php?id=50996&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=50996&r=support Expected behavior: http://bugs.php.net/fix.php?id=50996&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=50996&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=50996&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=50996&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=50996&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=50996&r=dst IIS Stability: http://bugs.php.net/fix.php?id=50996&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=50996&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=50996&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=50996&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=50996&r=mysqlcfg

« previous php.doc.bugs (#3860) next »