Skip to content

Commit 032f862

Browse files
committed
Drop support for crypt() without explicit salt
crypt() without salt generates a weak $1$ MD5 hash. It has been throwing a notice since 2013 and we provide a much better alternative in password_hash() (which can auto-generate salts for strong password hashes), so keeping this is just a liability.
1 parent f4b2497 commit 032f862

File tree

5 files changed

+16
-38
lines changed

5 files changed

+16
-38
lines changed

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,9 @@ PHP 8.0 UPGRADE NOTES
576576

577577
$ctx = stream_context_create(['http' => ['protocol_version' => '1.0']]);
578578
echo file_get_contents('http://example.org', false, $ctx);
579+
. Calling crypt() without an explicit salt is no longer supported. If you
580+
would like to produce a strong hash with an auto-generated salt, use
581+
password_hash() instead.
579582

580583
- Sysvmsg:
581584
. msg_get_queue() will now return an SysvMessageQueue object rather than a

ext/standard/basic_functions.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ function crc32(string $str): int {}
391391

392392
/* crypt.c */
393393

394-
function crypt(string $str, string $salt = UNKNOWN): string {}
394+
function crypt(string $str, string $salt): string {}
395395

396396
/* datetime.c */
397397

ext/standard/basic_functions_arginfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 010a6e0dee6d5e419e66eeefadd4dfabbbddfaca */
2+
* Stub hash: 28da5d6df91403aad82b5872453053dc41076a6a */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
55
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0)
@@ -597,7 +597,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_crc32, 0, 1, IS_LONG, 0)
597597
ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0)
598598
ZEND_END_ARG_INFO()
599599

600-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_crypt, 0, 1, IS_STRING, 0)
600+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_crypt, 0, 2, IS_STRING, 0)
601601
ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0)
602602
ZEND_ARG_TYPE_INFO(0, salt, IS_STRING, 0)
603603
ZEND_END_ARG_INFO()

ext/standard/crypt.c

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,6 @@ PHP_MSHUTDOWN_FUNCTION(crypt) /* {{{ */
7979
}
8080
/* }}} */
8181

82-
static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
83-
84-
/* Encode a string of bytes as Base64 */
85-
static void php_to64(char *s, int n) /* {{{ */
86-
{
87-
while (--n >= 0) {
88-
*s = itoa64[*s & 0x3f];
89-
s++;
90-
}
91-
}
92-
/* }}} */
93-
9482
PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const char *salt, int salt_len, zend_bool quiet)
9583
{
9684
char *crypt_res;
@@ -216,9 +204,8 @@ PHP_FUNCTION(crypt)
216204
size_t str_len, salt_in_len = 0;
217205
zend_string *result;
218206

219-
ZEND_PARSE_PARAMETERS_START(1, 2)
207+
ZEND_PARSE_PARAMETERS_START(2, 2)
220208
Z_PARAM_STRING(str, str_len)
221-
Z_PARAM_OPTIONAL
222209
Z_PARAM_STRING(salt_in, salt_in_len)
223210
ZEND_PARSE_PARAMETERS_END();
224211

@@ -227,23 +214,9 @@ PHP_FUNCTION(crypt)
227214
/* This will produce suitable results if people depend on DES-encryption
228215
* available (passing always 2-character salt). At least for glibc6.1 */
229216
memset(&salt[1], '$', PHP_MAX_SALT_LEN - 1);
217+
memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len));
230218

231-
if (salt_in) {
232-
memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len));
233-
} else {
234-
php_error_docref(NULL, E_NOTICE, "No salt parameter was specified. You must use a randomly generated salt and a strong hash function to produce a secure hash.");
235-
}
236-
237-
/* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */
238-
if (!*salt) {
239-
memcpy(salt, "$1$", 3);
240-
php_random_bytes_throw(&salt[3], 8);
241-
php_to64(&salt[3], 8);
242-
strncpy(&salt[11], "$", PHP_MAX_SALT_LEN - 11);
243-
salt_in_len = strlen(salt);
244-
} else {
245-
salt_in_len = MIN(PHP_MAX_SALT_LEN, salt_in_len);
246-
}
219+
salt_in_len = MIN(PHP_MAX_SALT_LEN, salt_in_len);
247220
salt[salt_in_len] = '\0';
248221

249222
if ((result = php_crypt(str, (int)str_len, salt, (int)salt_in_len, 0)) == NULL) {

ext/standard/tests/strings/crypt.phpt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ echo (CRYPT_EXT_DES) ? ((crypt($str, $salt2) === $res_2) ? 'EXT' : 'EXT - ERROR
1818
echo (CRYPT_MD5) ? ((crypt($str, $salt3) === $res_3) ? 'MD5' : 'MD5 - ERROR') : 'MD5', "\n";
1919
echo (CRYPT_BLOWFISH) ? ((crypt($str, $salt4) === $res_4) ? 'BLO' : 'BLO - ERROR') : 'BLO', "\n";
2020

21-
var_dump(crypt($str));
21+
try {
22+
var_dump(crypt($str));
23+
} catch (ArgumentCountError $e) {
24+
echo $e->getMessage(), "\n";
25+
}
2226

2327
?>
24-
--EXPECTF--
28+
--EXPECT--
2529
STD
2630
EXT
2731
MD5
2832
BLO
29-
30-
Notice: crypt(): No salt parameter was specified. You must use a randomly generated salt and a strong hash function to produce a secure hash. in %s on line %d
31-
string(%d) "%s"
33+
crypt() expects exactly 2 parameters, 1 given

0 commit comments

Comments
 (0)