-
-
Save BlaM/f3a9d535963900d1fbddc890c66f3891 to your computer and use it in GitHub Desktop.
<?php | |
// APR1-MD5 encryption method (windows compatible) | |
// https://gist.github.com/BlaM/f3a9d535963900d1fbddc890c66f3891 | |
// | |
// 2019-04-09 - https://github.com/BlaM - $salt | |
// 2022-03-04 - https://github.com/BlaM - fix php7 deprecation warning | |
// 2023-01-11 - https://github.com/BlaM and https://github.com/alecos71 - prepare for php8 sunset of str_shuffle | |
function crypt_apr1_md5($plainpasswd, $salt = null) { | |
if (empty($salt)) { | |
$chars = 'abcdefghijklmnopqrstuvwxyz012345689'; | |
$length = 8; | |
if (function_exists('random_int')) { | |
// PHP 7+ | |
$salt = ''; | |
for ($i = 0; $i < $length; $i++) { | |
$pos = random_int(0, strlen($chars) -1); | |
$salt .= substr($chars, $pos, 1); | |
} | |
} else if (function_exists('str_shuffle')) { | |
// PHP 4-8 | |
$salt = substr(str_shuffle($chars), 0, $length); | |
} else { | |
throw new Exception('Not implemented'); | |
} | |
} elseif (substr($salt, 0, 6) == '$apr1$') { | |
$salt = explode('$', $salt); | |
$salt = $salt[2]; | |
} | |
$tmp = ""; | |
$len = strlen($plainpasswd); | |
$text = $plainpasswd . '$apr1$' . $salt; | |
$bin = pack("H32", md5($plainpasswd . $salt . $plainpasswd)); | |
for ($i = $len; $i > 0; $i -= 16) { $text .= substr($bin, 0, min(16, $i)); } | |
for ($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(0) : substr($plainpasswd, 0, 0); } | |
$bin = pack("H32", md5($text)); | |
for ($i = 0; $i < 1000; $i++) { | |
$new = ($i & 1) ? $plainpasswd : $bin; | |
if ($i % 3) $new .= $salt; | |
if ($i % 7) $new .= $plainpasswd; | |
$new .= ($i & 1) ? $bin : $plainpasswd; | |
$bin = pack("H32", md5($new)); | |
} | |
for ($i = 0; $i < 5; $i++) { | |
$k = $i + 6; | |
$j = $i + 12; | |
if ($j == 16) $j = 5; | |
$tmp = $bin[$i].$bin[$k].$bin[$j].$tmp; | |
} | |
$tmp = chr(0).chr(0).$bin[11].$tmp; | |
$tmp = strtr(strrev(substr(base64_encode($tmp), 2)), | |
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", | |
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); | |
return "$"."apr1"."$".$salt."$".$tmp; | |
} |
Hashes are "undecryptable".
Think of it as "10 + 15 + 23 = 48". You'll never be able to go back to "decrypt" 48 to the original math equation. Only one direction.
thanks u so much
https://wiki.php.net/rfc/deprecations_php_8_3
The following functions will be deprecated in Php 8.3 and removed in Php 9.0.
- mt_rand
- mt_srand
- mt_getrandmax
- rand
- srand
- getrandmax
- array_rand
- shuffle
- str_shuffle
random_int() instead is safe and not deprecated.
str_shuffle is the one inside your script. Please fix it!
Here is my proposal to fix:
function crypt_apr1_md5($plainpasswd, $salt = null) {
if (empty($salt)) {
$chars = 'abcdefghijklmnopqrstuvwxyz012345689';
$length = 35;
$random = '';
for ($i = 0; $i < $length; $i++) {
$pos = random_int(0, strlen($chars) -1);
$random .= substr($chars, $pos, 1);
}
$salt = substr($random, 0, 8);
// $salt = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 8); /* Deprecated */
} elseif (substr($salt, 0, 6) == '$apr1$') {
$salt = explode('$', $salt);
$salt = $salt[2];
}
$tmp = "";
$len = strlen($plainpasswd);
$text = $plainpasswd.'$apr1$'.$salt;
$bin = pack("H32", md5($plainpasswd.$salt.$plainpasswd));
for ($i = $len; $i > 0; $i -= 16) { $text .= substr($bin, 0, min(16, $i)); }
for ($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(0) : substr($plainpasswd, 0, 0); }
$bin = pack("H32", md5($text));
for ($i = 0; $i < 1000; $i++) {
$new = ($i & 1) ? $plainpasswd : $bin;
if ($i % 3) $new .= $salt;
if ($i % 7) $new .= $plainpasswd;
$new .= ($i & 1) ? $bin : $plainpasswd;
$bin = pack("H32", md5($new));
}
for ($i = 0; $i < 5; $i++) {
$k = $i + 6;
$j = $i + 12;
if ($j == 16) $j = 5;
$tmp = $bin[$i].$bin[$k].$bin[$j].$tmp;
}
$tmp = chr(0).chr(0).$bin[11].$tmp;
$tmp = strtr(strrev(substr(base64_encode($tmp), 2)),
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
return "$"."apr1"."$".$salt."$".$tmp;
}
What do you think? Is quite safe?
Thank you for the heads up. Your suggestion is probably even more cryptographically safe than the old str_shuffle approach. I'll base my update on your suggestion, but I'll "optimize" it a bit (there is no need to randomize 35 characters and then throw everything after character 8 away - randomizing just 8 is enough ;) )
Well done!
Please, pay attention to this:
Apache in Windows requires the salt, without fails to authenticate. The rest is OK.
How to decrypt