In der Hoffnung, dass es gefällt stelle ich das hier mal online. Könnte für jene nützlich sein, die sich mit alten PHP-Versionen herumschlagen müssen oder nicht wissen, für welche sie programmieren.
Zum Testen in Zeile 2 den Funktionsaufruf test_me(); "scharfschalten" und die Funktion test_hash_passwd() durch die Kommentare modifizieren.
<?php
#test_me();
error_reporting(0);
## Erzeugt gesalzte Passwörter nach "bester" Möglichkeit. Reihenfolge mit
## * password_hash
## * CRYPT_SHA512
## * CRYPT_SHA256
## * CRYPT_BLOWFISH
## * Apache MD5 - $apr1$ (als Fallback)
## und kann diese verifizieren
## verifiziert zusätzlich auch Passwörter, deren Hash früher mal mit
## * htpasswd -nbs myName myPassword (SHA1, {sha})
## * gesalzenem md5 ( siehe test_hash_passwd() )
## * gesalzenem sha1 ( siehe test_hash_passwd() )
## erzeugt wurde...
function create_salt($l=16, $allowed='1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ./') {
$salt='';
for ( $i = 0; $i < $l; $i++ ) {
$salt .= $allowed{rand( 0, strlen($allowed) - 1 )};
}
return $salt;
}
function fastix_hash_passwd ($string) {
if ( function_exists ('password_hash') ) {
return password_hash($string, PASSWORD_DEFAULT);
} else {
if ( function_exists ('crypt') and defined('CRYPT_SHA512') and CRYPT_SHA512 ) {
return crypt( $string, '$6$rounds=5000$' . create_salt() );
} else if ( function_exists ('crypt') and defined('CRYPT_SHA256') and CRYPT_SHA256 ) {
return crypt( $string, '$5$rounds=5000$' . create_salt() );
} else if ( function_exists ('crypt') and defined('CRYPT_BLOWFISH') and CRYPT_BLOWFISH ) {
if ( version_compare(phpversion(), '5.3.7', '>') ) {
return crypt( $string, '$2y$12$' . create_salt(22) );
} else {
return crypt( $string, '$2a$12$' . create_salt(22) );
}
} else {
# Fallback: Apache md5 - $apr1$
$salt = create_salt(8, 'abcdefghijklmnopqrstuvwxyz0123456789');
# Code from http://php.net/manual/de/function.crypt.php, comment No. 8:
$len = strlen($string);
$tmp='';
$text = $string.'$apr1$'.$salt;
$bin = pack("H32", md5($string.$salt.$string));
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) : $string{0}; }
$bin = pack("H32", md5($text));
for($i = 0; $i < 1000; $i++) {
$new = ($i & 1) ? $string : $bin;
if ($i % 3) $new .= $salt;
if ($i % 7) $new .= $string;
$new .= ($i & 1) ? $bin : $string;
$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;
}
}
header('HTTP/1.1 500 Script Generated Error (NO HASH-METHOD Found)');
exit;
}
function fastix_check_passwd ($string, $string_hashed, $error_exit=false) {
# htpasswd -nbm myName myPassword
if ( '$apr1$' == substr($string_hashed, 0, 6) ) {
list ($dummy, $method, $salt, $rest)=explode('$', $string_hashed, 4);
# Code From http://php.net/manual/de/function.crypt.php, comment No. 8:
$len = strlen($string);
$tmp='';
$text = $string.'$apr1$'.$salt;
$bin = pack("H32", md5($string.$salt.$string));
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) : $string{0}; }
$bin = pack("H32", md5($text));
for($i = 0; $i < 1000; $i++) {
$new = ($i & 1) ? $string : $bin;
if ($i % 3) $new .= $salt;
if ($i % 7) $new .= $string;
$new .= ($i & 1) ? $bin : $string;
$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");
#$hashed = "$"."apr1"."$".$salt."$".$tmp;
if ( $rest == $tmp) { return 'bestaetigt:apache2-apr1'; }
}
# htpasswd -nbs myName myPassword
if ( '{SHA}' == substr($string_hashed, 0, 5) ) {
$hash='{SHA}' . base64_encode(sha1($string, TRUE));
if ( $hash == $string_hashed) { return 'bestaetigt:apache2-sha1'; }
}
if ( function_exists ('password_verify') ) {
if ( password_verify($string, $string_hashed) ) { return 'bestaetigt:password_verify()'; }
}
if ( function_exists ('crypt') ) {
list( $dummy, $method, $rest ) = explode( '$', $string_hashed, 3 );
if ( '2y' == $method or '2a' == $method ) {
list ($dummy, $method, $rounds, $rest)=explode('$', $string_hashed, 4);
$salt = substr($rest, 0, 22);
if ( $string_hashed == crypt($string, '$' . $method . '$' . $rounds . '$' . $salt) ) { return 'bestaetigt:crypt():'.$method; }
}
if ( '6' == $method or '5' == $method or '1' == $method ) {
list ($dummy, $method, $rounds, $salt, $rest) = explode('$', $string_hashed, 5);
if ( $string_hashed == crypt($string, '$' . $method . '$' . $rounds . '$' . $salt) ) { return 'bestaetigt:crypt()'.$method; }
}
}
if ( '1' == $method ) {
trigger_error("Warnung: Das Passwort ist nicht ausreichend sicher gehasht.", E_USER_NOTICE);
list( $dummy, $method, $rounds, $salt, $rest )=explode( '$', $string_hashed, 5 );
$rounds = str_replace('rounds=', '', $rounds);
for ( $i = 0; $i < $rounds; $i++ ) {
$string = md5($salt.$string);
}
$string = '$1$rounds=' . $rounds . '$' . $salt . '$' . $string;
if ( $string_hashed == $string ) { return 'bestaetigt:md5()'; }
}
if ( 'sha1' == $method ) {
trigger_error("Warnung: Das Passwort ist nicht ausreichend sicher gehasht.", E_USER_NOTICE);
list ($dummy, $method, $rounds, $salt, $rest)=explode('$', $string_hashed, 5);
$rounds = str_replace( 'rounds=', '', $rounds );
for ( $i = 0; $i < $rounds; $i++ ) {
$string = sha1($salt.$string);
}
$string = '$sha1$rounds=' . $rounds . '$' . $salt . '$' . $string;
if ( $string_hashed == $string ) { return 'bestaetigt:sha1()'; }
}
if ( $error_exit ) { trigger_error("Unbekannte Methode oder falsches Passwort.", $error_exit); }
return false;
}
### Tests ####
function test_hash_passwd ($string) {
# return password_hash($string, PASSWORD_DEFAULT);
# return crypt( $string, '$6$rounds=5000$' . create_salt() );
# return crypt( $string, '$5$rounds=5000$' . create_salt() );
return crypt( $string, '$2y$12$' . create_salt(22) );
return crypt( $string, '$2a$12$' . create_salt(22) );
$salt=create_salt(32); for ( $i=0; $i<50000; $i++ ) { $string=sha1($salt.$string); } return '$sha1$rounds=50000$' . $salt . '$' . $string;
$salt=create_salt(32); for ( $i=0; $i<50000; $i++ ) { $string=md5($salt.$string); } return '$1$rounds=50000$' . $salt . '$' . $string;
}
function test_me() {
error_reporting(E_ALL);
$string='Dieses Passwort ist vollkommen richtig';
$string_hashed=test_hash_passwd ($string);
echo "'$string'\n", "'$string_hashed'\n", fastix_check_passwd($string, $string_hashed, E_USER_ERROR), "\n";
$string='Dieses Passwort ist nur fast richtig:2'; echo "Gegentest: '$string'\n", fastix_check_passwd($string, $string_hashed, E_USER_NOTICE), "\n";
print fastix_check_passwd('myPassword', '{SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE=')."\n";
print fastix_check_passwd('myPassword', '$apr1$r31.....$HqJZimcKQFAMYayBlzkrA/')."\n";
}