This has been reported as 189958 broken /usr/bin/crypt but this has a much more serisous impact than is incidated that bug report and the accompanying comments. For that reason, I am submitting a new bug report. On FreeBSD 9.3 Release, the crypt(3) function does not behave as documented and also not as on FreeBSD 8.4. The documented and expected default is tu generate the legacy DES encryption but this has been changed. The crypt() function is used directly by Perl and PHP and affects these as well. The crypt(3) C library routine is used by Perl/PHP. This change has broken a large number of other things. While there is no argument about the 'strength' of the hash/encryption, the documentation states that it will behave in a specific manner, and as far as I can tell with a quick scan of the FreeBSD archives, there has been no discussion of the impact of making this change. I am surprised that one of the core functions behavior (crypt) was modified and this was not put into the FreeBSD 9.3 release notes. I would strongly suggest that you publicize this and send out instructions on how to a) make the 'des' encryption the default b) recompile everything that uses crypt and is statically linked c) warn Perl and PHP users about this impact so they can update their Perl and PHP. (Note, I might be wrong about PHP, but I checked Perl and it uses the -lcrypt library). Details: NAME crypt -- Trapdoor encryption LIBRARY Crypt Library (libcrypt, -lcrypt) SYNOPSIS #include <unistd.h> char * crypt(const char *key, const char *salt); const char * crypt_get_format(void); int crypt_set_format(const char *string); DESCRIPTION The crypt() function performs password hashing with additional code added to deter key search attempts. Different algorithms can be used to in the hash. Currently these include the NBS Data Encryption Standard (DES), MD5 hash, NT-Hash (compatible with Microsoft's NT scheme) and Blowfish. The algorithm used will depend upon the format of the Salt (following the Modular Crypt Format (MCF)), if DES and/or Blowfish is installed or not, and whether crypt_set_format() has been called to change the default. The first argument to crypt is the data to hash (usually a password), in a NUL-terminated string. The second is the salt, in one of three forms: Extended If it begins with an underscore (``_'') then the DES Extended Format is used in interpreting both the key and the salt, as outlined below. Modular If it begins with the string ``$digit$'' then the Mod- ular Crypt Format is used, as outlined below. Traditional If neither of the above is true, it assumes the Tradi- tional Format, using the entire string as the salt (or the first portion). ... Traditional crypt: The algorithm used will depend upon whether crypt_set_format() has been called and whether a global default format has been specified. Unless a global default has been specified or crypt_set_format() has set the for- mat to something else, the built-in default format is used. This is cur- rently DES if it is available, or MD5 if not. The crypt_get_format() function returns a constant string that represents the name of the algorithm currently used. Valid values are `des', `blf', `md5', `sha256', `sha512' and `nth'. The crypt_set_format() function sets the default encoding format accord- ing to the supplied string. Test Program: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main( int argc, char **argv, char **envp ) { const char *password = "testpassword"; const char *salt = "_testpassword"; const char *format = crypt_get_format(); const char *output = crypt(password,password); fprintf( stdout, "Password '%s', format '%s', output '%s'\n", password, format, output ); output = crypt(password,salt); fprintf( stdout, "Password '%s', salt '%s', output '%s'\n", password, salt, output ); int status = crypt_set_format("des"); format = crypt_get_format(); output = crypt(password,password); fprintf( stdout, "status %d, Password '%s', format '%s', output '%s'\n", status, password, format, output ); output = crypt(password,salt); fprintf( stdout, "Password '%s', salt '%s', output '%s'\n", password, salt, output ); exit( 0 ); }FreeBSD 9.3: Pssword 'testpassword', format 'sha512', output '$6$testpassword$QvM4M3dhSAaiMa6EthlRMq3g8efvl1GySUxAyuXAIN. DmgGZuDLqKqi.wZ/PzWadf7YYxAKVlXmjq9ajS1R7y0' Password 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA' status 1, Password 'testpassword', format 'des', output 'tek4edTZE898g' Password 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA' assword 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA' FreeBSD 8.4: Password 'testpassword', format 'des', output 'tek4edTZE898g' Password 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA' status 1, Password 'testpassword', format 'des', output 'tek4edTZE898g' Password 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA' From the FreeBSD 8.4 source: /usr/src/lib/libcrypt/crypt.c: static const struct { const char *const name; char *(*const func)(const char *, const char *); const char *const magic; } crypt_types[] = { #ifdef HAS_DES { "des", crypt_des, NULL { "md5", crypt_md5, "$1$" }, From the FreeBSD 9.3 source. Note that the default format is set to sha512, not des: /* * List of supported crypt(3) formats. The first element in the list will * be the default. */ static const struct crypt_format { const char *const name; char *(*const func)(const char *, const char *); const char *const magic; } crypt_formats[] = { /* default format */ { "sha512", crypt_sha512, "$6$" }, /* other supported formats */ { "md5", crypt_md5, "$1$" }, #ifdef HAS_BLOWFISH { "blf", crypt_blowfish, "$2" }, #endif { "nth", crypt_nthash, "$3$" }, { "sha256", crypt_sha256, "$5$" }, #ifdef HAS_DES { "des", crypt_des, "_" }, #endif }, #endif /* sentinel */ { NULL, NULL, NULL } }; Suggestion: static const struct crypt_format { const char *const name; char *(*const func)(const char *, const char *); const char *const magic; } crypt_formats[] = { /* default format */ #ifdef HAS_DES { "des", crypt_des, "_" }, #endif { "sha512", crypt_sha512, "$6$" }, /* other supported formats */ { "md5", crypt_md5, "$1$" }, #ifdef HAS_BLOWFISH { "blf", crypt_blowfish, "$2" }, #endif { "nth", crypt_nthash, "$3$" }, { "sha256", crypt_sha256, "$5$" }, /* sentinel */ { NULL, NULL, NULL } };
*** This bug has been marked as a duplicate of bug 192277 ***