PHP Doku:: Einweg-String-Verschlüsselung (Hashbildung) - function.crypt.html

Verlauf / Chronik / History: (1) anzeigen

Sie sind hier:
Doku-StartseitePHP-HandbuchFunktionsreferenzTextverarbeitungZeichenkettenString-Funktionencrypt

Ein Service von Reinhard Neidl - Webprogrammierung.

String-Funktionen

<<crc32

echo>>

crypt

(PHP 4, PHP 5)

cryptEinweg-String-Verschlüsselung (Hashbildung)

Beschreibung

string crypt ( string $str [, string $salt ] )

crypt() gibt einen Hash-String zurück, der unter Verwendung des DES-basierenden Algorithmus Unix-Standard-Verschlüsselungsalgorithmus erstellt wurde. Dieser Algorithmus muss auf dem System verfügbar sein.

Einige Betriebssystem unterstützen mehr als eine Methode zur Verschlüsselung. So wird manchmal der DES- durch einen MD5-Algorithmus ersetzt. Der verwendete Schlüssel wird durch das Salt-Argument bestimmt. Zum Installationszeitpunkt untersucht PHP die vorhandenen Möglichkeiten und wird, abhängig vom Ergebnis dieser Prüfung, auch andere Schlüssel-Typen zulassen. Wird kein Salt unterstützt, erzeugt PHP per Voreinstellung einen 2-Zeichen DES-Salt, es sei denn, auf ihrem System ist MD5 der Standardverschlüsselungstyp. In diesem Fall wird PHP einen zufälligen MD5-kompatiblen Salt generieren. PHP setzt eine Konstante namens CRYPT_SALT_LENGTH, die Ihnen sagt, ob ihr System einen regulären 2-Zeichen-Salt oder den längeren 12-Zeichen-Salt unterstützt.

Die Standard-DES-Verschlüsselung crypt() enthält den Salt als erste 2 Zeichen der Ausgabe. Ebenso werden nur die ersten acht Zeichen von str berücksichtigt; verwenden Sie also einen längeren String, der mit den gleichen 8 Buchstaben beginnt, so erhalten Sie denselben Rückgabewert (sofern Sie ebenfalls den gleichen Salt nutzen).

Auf Systemen, wo die crypt()-Funktion mehrere Verschlüsselungsarten unterstützt, werden die folgenden Konstanten auf 0 oder 1 gesetzt, je nachdem, ob der entsprechende Typ verfügbar ist:

  • CRYPT_STD_DES - Standard DES-Schlüssel mit 2-Zeichen-Salt
  • CRYPT_EXT_DES - Erweiterte DES-basierte Verschlüsselung mit einem 9-Zeichen-Salt
  • CRYPT_MD5 - MD5-Verschlüsselung mit 12-Zeichen-Salt, beginnend mit $1$
  • CRYPT_BLOWFISH - Blowfish-Verschlüsselung mit 16-Zeichen-Salt, beginnend mit $2$ oder $2a$

Hinweis:

Seit PHP 5.3.0 enthält PHP eine eigene Implementation und verwendet diese, wenn das System einen oder mehrere der Algorithmen nicht unterstützt.

Parameter-Liste

str

Die zu verschlüsselnde Zeichenkette.

salt

Ein optionaler Salt-String, der die Schlüsselbasis bildet. Sofern nicht angegeben, wird von PHP ein zufälliger Wert bei jedem Aufruf der Funktion generiert.

Wenn Sie das gegebene Salt benutzen, sollten Sie beachten, dass dieser Wert nur einmal bestimmt wird. Rufen Sie diese Funktion nun mehrmals auf, beeinträchtigt das nicht nur das Ergebnis, sondern unter Umständen auch die Sicherheit.

Rückgabewerte

Gibt die verschlüsselte Zeichenkette zurück.

Changelog

Version Beschreibung
5.3.0 PHP enthält jetzt eine eigene Implementation der MD5-Crypt, Standard DES, Extended DES und des Blowfish-Algorithmus und verwendet diese, wenn das System eine oder mehrere der Algorithmen nicht unterstützt.

Beispiele

Beispiel #1 crypt()-Beispiele

<?php
$passwort 
crypt('mein_Pwd'); // Der Salt wird automatisch generiert

/* Sie sollten das vollständige Ergebnis von crypt() als Salt zum
   Passwort-Vergleich übergeben, um Problemen mit unterschiedlichen
   Hash-Algorithmen vorzubeugen. (Wie bereits ausgeführt, verwendet
   ein Standard-DES-Passwort-Hash einen 2-Zeichen-Salt, ein
   MD5-basierter hingegen nutzt 12 Zeichen. */
if (crypt($benutzer_eingabe$passwort) == $passwort) {
   echo 
"Passwort stimmt überein!";
}
?>

Beispiel #2 Verwendung von crypt() für htpasswd

<?php
// Passwort setzen
$passwort 'mein_Pwd';

// Hash mit automatisch erstelltem Salt generieren
$hash crypt($passwort);
?>

Beispiel #3 Verwendung von crypt() mit verschiedenen Verschlüsselungsarten

<?php
if (CRYPT_STD_DES == 1) {
    echo 
'Standard DES: ' crypt('rasmuslerdorf''rl') . "\n";
}

if (
CRYPT_EXT_DES == 1) {
    echo 
'Extended DES: ' crypt('rasmuslerdorf''_J9..rasm') . "\n";
}

if (
CRYPT_MD5 == 1) {
    echo 
'MD5:          ' crypt('rasmuslerdorf''$1$rasmusle$') . "\n";
}

if (
CRYPT_BLOWFISH == 1) {
    echo 
'Blowfish:     ' crypt('rasmuslerdorf''$2a$07$usesomesillystringforsalt$') . "\n";
}
?>

Das oben gezeigte Beispiel erzeugt eine ähnliche Ausgabe wie:

Standard DES: rl.3StKT.4T8M
Extended DES: _J9..rasmBYk8r9AiWNc
MD5:          $1$rasmusle$rISCgZzpwk3UhDidwXvin0
Blowfish:     $2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi

Anmerkungen

Hinweis: Es existiert keine decrypt Funktion, da crypt() eine Einweg-Verschlüsselung ist.

Siehe auch

  • md5() - Errechnet den MD5-Hash eines Strings
  • Die Mcrypt-Erweiterung
  • Lesen Sie die Man-Pages ihres Unix-Systems, wenn Sie weitere Informationen zu Crypt benötigen.


15 BenutzerBeiträge:
- Beiträge aktualisieren...
Robin Leffmann
25.12.2010 15:23
The salts for crypt() must follow the usual base64 ASCII pattern (./0-9A-Za-z only), but the payload string can contain any binary data.
Thomas Praxl
10.01.2010 18:28
Note that crypt can cause hangs on Windows OS when used with a salt. This applies only to certain circumstances.
php at nospam dot nowhere dot com
27.08.2009 4:21
The makesalt() function code below when used to create an MD5 salt, produces a salt with characters not typically in a salt used by operating system crypt functions.  Some of these characters may have unintended side effects depending on how they are used - including the following: @ ` ~ \ | {}.

I am using the following to create MD5-Crypt hashes, (yes, I am assuming CRYPT_MD5 support is present).

<?php
function md5crypt($password){
   
// create a salt that ensures crypt creates an md5 hash
   
$base64_alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                   
.'abcdefghijklmnopqrstuvwxyz0123456789+/';
   
$salt='$1$';
    for(
$i=0; $i<9; $i++){
       
$salt.=$base64_alphabet[rand(0,63)];
    }
   
// return the crypt md5 password
   
return crypt($password,$salt.'$');
}
?>
sdc
17.07.2007 17:49
ECB is one of the least secure block cipher modes (Wikipedia has some good information about these: http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation) because it is the only mode, out of the one's available for use with MCRYPT, that does not actually use the IV provided. Note: PHP will emit an E_WARNING if the IV is missing or if its length is not equal to the size mandated by mcrypt_get_iv_size().

In response to <addiakogiannis at isds dot gr>, even though the IV is randomly generated in the encryption and decryption functions, the output remains the same given the same plaintext and key because the mode is ECB. If a different mode is used, the IV must be preserved (say, by concatenation with the ciphertext) in order for the ciphertext to be decrypted properly. That is:

<?php

//changing all instances of MCRYPT_MODE_ECB to MCRYPT_MODE_CFB

function RIJNDAEL_encrypt($text){

   
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB);
   
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
   
$key = "This is a very secret key";
    return
base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CFB, $iv));
  
}

function
RIJNDAEL_decrypt($text){

   
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB);
   
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
   
$key = "This is a very secret key";
 
//I used trim to remove trailing spaces
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_CFB, $iv));
  
}

//example
echo RIJNDAEL_decrypt(RIJNDAEL_encrypt('Her name was lola!'));

?>

...will output a random, 18-character string. Thus, the length of the plaintext is preserved, but the data is completely corrupted.
addiakogiannis at isds dot gr
13.07.2007 12:46
Two siple functions for encrypting and decrypting with RIJNDAEL 256

function RIJNDAEL_encrypt($text){

    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $key = "This is a very secret key";
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv));
   
}

function RIJNDAEL_decrypt($text){

    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $key = "This is a very secret key";
  //I used trim to remove trailing spaces
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_ECB, $iv));
   
}

//example
echo RIJNDAEL_decrypt(RIJNDAEL_encrypt('Her name was lola!'));
leth at nowhere dot not
6.04.2007 16:51
for me(on OpenBSD4.0+Apache 1.3(standard)+php4.3.10) blowfish seems to work if you do something like this:

    if (CRYPT_BLOWFISH == 1)
    {
        $salt="this should really be a long line of salt";
        $blowfish_salt = "\$2a\$07\$".substr($salt, 0, CRYPT_SALT_LENGTH);
        echo crypt($pass, $blowfish_salt);
    }

of course with $salt set as a good long salt.
Jou
6.04.2007 10:52
I found out that you can use php:s crypt function to change  the user/root password in Linux distributions (at least in Slackware).

You just have to change the encrypted password for the user in the /etc/shadow file with the output from crypt("newpassword");
mikey_nich (at) hotmáil . com
4.03.2007 16:47
Are you using Apache2 on f.i. WinXP and want to create .htpasswd files via php? Then you need to use the APR1-MD5 encryption method. Here is a function for that:

<?php

function crypt_apr1_md5($plainpasswd) {
   
$salt = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 8);
   
$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) : $plainpasswd{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;
}

?>
tserong at sgi dot com
14.12.2006 9:18
Blowfish doesn't use a sixteen character salt, it uses sixteen *bytes* of salt.  So (courtesy of the docs for the Crypt::Eksblowfish::Bcrypt Perl module), it's:

    "$2", optional "a", "$", two digits, "$", and 22 base 64 digits

If the salt is not long enough, crypt will return "*0" and you will have no idea what is wrong.  Interestingly, the example in the documentation with a trailing '$' in the salt does not work.  Replace the '$' with a '.', and the output appears as advertised.
picolobo at pilab dot dyndns dot org
21.09.2006 22:49
I had problems with ENCRYPT MySQL function when i tried to compare with the encrypted password (with ENCRYPT).

Another solution i read from "UNIX Advanced programming" where i found about the UNIX system call "crypt()":

Password="tB" //The two first letters of encrypted password

SELECT password from users where Password=ENCRYPT('".$_POST['password']."',Password)

mysql> select password from users where password=encrypt('pasword','tB');
+---------------+
| password      |
+---------------+
| tBY8OVuabSiTU |
+---------------+
1 row in set (0.01 sec)

Bye.

> topace at lightbox dot org
> 22-Sep-2005 06:34
>
> To authenticate against a stored crypt in MySQL, simply use:
>
> SELECT ................
>           AND Password=ENCRYPT('".$_POST['password']."',Password)
solar at openwall dot com
24.12.2005 8:20
With different password hashing methods supported on different systems and with the need to generate salts with your own PHP code in order to use the more advanced / more secure methods, it takes special knowledge to use crypt() optimally, producing strong password hashes.  Other message digest / hashing functions supported by PHP, such as md5() and sha1(), are really no good for password hashing if used naively, resulting in hashes which may be brute-forced at rates much higher than those possible for hashes produced by crypt().

I have implemented a PHP password hashing framework (in PHP, tested with all of PHP 3, 4, and 5) which hides the complexity from your PHP applications (no need for you to worry about salts, etc.), yet does things in almost the best way possible given the constraints of the available functions.  The homepage for the framework is:

http://www.openwall.com/phpass/

I have placed this code in the public domain, so there are no copyrights or licensing restrictions to worry about.

P.S. I have 10 years of experience in password (in)security and I've developed several other password security tools and libraries.  So most people can feel confident they're getting this done better by using my framework than they could have done it on their own.
hotdog (at) gmx (dot) net
16.11.2005 16:34
WRONG:

$mypassword = "toto";
$smd5_pass = "{SMD5}......." // in openldap

if (preg_match ("/{SMD5}/i", $smd5_pass))
 {
  $encrypted = substr($md5_pass, 6);
  $hash = base64_decode($encrypted);
  $salt = substr($hash,16);
  $mhashed =  mhash(MHASH_MD5, $mypassword . $salt) ;
  $without_salt = explode($salt,$hash_hex);
   if ($without_salt[0] == $mhashed) {
    echo "Password verified <br>";
    } else {
    echo "Password Not verified<br>";
    }
 }

$without_salt = explode($salt,$hash_hex); should be $without_salt = explode($salt,$hash);

RIGHT:

$mypassword = "toto";
$smd5_pass = "{SMD5}......." // in openldap

if (preg_match ("/{SMD5}/i", $smd5_pass))
 {
  $encrypted = substr($md5_pass, 6);
  $hash = base64_decode($encrypted);
  $salt = substr($hash,16);
  $mhashed =  mhash(MHASH_MD5, $mypassword . $salt) ;
  $without_salt = explode($salt,$hash);
   if ($without_salt[0] == $mhashed) {
    echo "Password verified <br>";
    } else {
    echo "Password Not verified<br>";
    }
 }
Vlad Alexa Mancini mancin at nextcode dot org
15.05.2005 22:57
cleaner version of shadow() and with more ascii chars

<?php

function shadow ($input){
         for (
$n = 0; $n < 9; $n++){
             
$s .= chr(rand(64,126));
         }
        
$seed "$1$".$s."$";
        
$return = crypt($input,$seed);
    return
$return;
}

>
thorhajo at gmail dot com
3.09.2004 0:34
Here's a little function I wrote to generate MD5 password hashes in the format they're found in /etc/shadow:

function shadow($password)
{
  $hash = '';
  for($i=0;$i<8;$i++)
  {
    $j = mt_rand(0,53);
    if($j<26)$hash .= chr(rand(65,90));
    else if($j<52)$hash .= chr(rand(97,122));
    else if($j<53)$hash .= '.';
    else $hash .= '/';
  }
  return crypt($password,'$1$'.$hash.'$');
}

I've written this so that each character in the a-zA-Z./ set has a 1/54 of a chance of being selected (26 + 26 + 2 = 54), thus being statistically even.
aidan at php dot net
5.07.2004 16:52
Text_Password allows one to create pronounceable and unpronounceable passwords.

http://pear.php.net/package/text_password



PHP Powered Diese Seite bei php.net
The PHP manual text and comments are covered by the Creative Commons Attribution 3.0 License © the PHP Documentation Group - Impressum - mail("TO:Reinhard Neidl",...)