La mejor manera de usar PHP para cifrar y descifrar contraseñas? [duplicar]


Posible Duplicado:
Cifrado PHP de 2 vías: Necesito almacenar contraseñas que se puedan recuperar

Planeo almacenar información de cuentas extranjeras para mis usuarios en mi sitio web, también conocido como nombre de usuario y contraseñas rapidshare, etc... Quiero mantener la información segura, pero sé que si hash su información, no puedo recuperarla para su uso posterior.

Base64 es capaz de descifrar, por lo que no tiene sentido usar eso simplemente. Mi idea es codificar al usuario y pase antes y después de que se base64ed de esa manera, incluso después de descifrarlo, se obtiene un texto de aspecto divertido si intenta descifrar. ¿Hay una función php que acepte valores que hagan un scramble único de una cadena y lo des-scramble más tarde cuando se reinputa el valor?

Alguna sugerencia?

Author: Community, 2009-08-17

8 answers

No debe cifrar contraseñas, en su lugar debe hash utilizando un algoritmo como bcrypt. Esta respuesta explica cómo implementar correctamente el hashing de contraseñas en PHP. Aún así, aquí está cómo cifrar / descifrar:

$key = 'password to (en/de)crypt';
$string = ' string to be encrypted '; // note the spaces

Para Cifrar:

$iv = mcrypt_create_iv(
    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
    MCRYPT_DEV_URANDOM
);

$encrypted = base64_encode(
    $iv .
    mcrypt_encrypt(
        MCRYPT_RIJNDAEL_128,
        hash('sha256', $key, true),
        $string,
        MCRYPT_MODE_CBC,
        $iv
    )
);

Para Descifrar:

$data = base64_decode($encrypted);
$iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));

$decrypted = rtrim(
    mcrypt_decrypt(
        MCRYPT_RIJNDAEL_128,
        hash('sha256', $key, true),
        substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),
        MCRYPT_MODE_CBC,
        $iv
    ),
    "\0"
);

Advertencia : El ejemplo anterior encripta la información, pero no autentica el texto cifrado para evitar la manipulación. Usted debe no dependen del cifrado no autenticado para la seguridad, especialmente porque el código proporcionado es vulnerable a los ataques de relleno de oracle.

Véase también:

Además, no solo use una "contraseña" para una clave de cifrado. Las claves de cifrado son aleatorias cadena.


Demo en 3v4l.org :

echo 'Encrypted:' . "\n";
var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="

echo "\n";

echo 'Decrypted:' . "\n";
var_dump($decrypted); // " string to be encrypted "
 292
Author: Alix Axel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:59

Advertencia de seguridad: Esta clase no es segura. Está usando Rijndael256-ECB, que no es semánticamente seguro. Solo porque " funciona "no significa que"es seguro". Además, elimina los espacios de cola después debido a que no usa el relleno adecuado.

Encontrado esta clase recientemente, funciona como un sueño!

class Encryption {
    var $skey = "yourSecretKey"; // you can change it

    public  function safe_b64encode($string) {
        $data = base64_encode($string);
        $data = str_replace(array('+','/','='),array('-','_',''),$data);
        return $data;
    }

    public function safe_b64decode($string) {
        $data = str_replace(array('-','_'),array('+','/'),$string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }

    public  function encode($value){ 
        if(!$value){return false;}
        $text = $value;
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->skey, $text, MCRYPT_MODE_ECB, $iv);
        return trim($this->safe_b64encode($crypttext)); 
    }

    public function decode($value){
        if(!$value){return false;}
        $crypttext = $this->safe_b64decode($value); 
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->skey, $crypttext, MCRYPT_MODE_ECB, $iv);
        return trim($decrypttext);
    }
}

Y para llamarlo:

$str = "My secret String";

$converter = new Encryption;
$encoded = $converter->encode($str );
$decoded = $converter->decode($encoded);    

echo "$encoded<p>$decoded";
 34
Author: wilsonpage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-15 08:21:15

Advertencia de Seguridad: Este código no es seguro.

Ejemplo de trabajo

define('SALT', 'whateveryouwant'); 

function encrypt($text) 
{ 
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
} 

function decrypt($text) 
{ 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SALT, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
} 

$encryptedmessage = encrypt("your message"); 
echo decrypt($encryptedmessage); 
 18
Author: stasl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-15 08:15:43

Una cosa que debe tener muy en cuenta cuando se trata de cifrado:

Tratar de ser inteligente e inventar lo propio generalmente te dejará con algo inseguro.

Probablemente sería mejor usar una de las extensiones de criptografía que vienen con PHP.

 12
Author: Sebastian Paaske Tørholm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-17 16:50:07

Advertencia de seguridad : Este código es inseguro. Además de ser vulnerable a ataques de texto cifrado elegido, su dependencia de unserialize() lo hace vulnerable a la Inyección de Objetos PHP.

Para manejar una cadena / matriz utilizo estas dos funciones:

function encryptStringArray ($stringArray, $key = "Your secret salt thingie") {
 $s = strtr(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), serialize($stringArray), MCRYPT_MODE_CBC, md5(md5($key)))), '+/=', '-_,');
 return $s;
}

function decryptStringArray ($stringArray, $key = "Your secret salt thingie") {
 $s = unserialize(rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode(strtr($stringArray, '-_,', '+/=')), MCRYPT_MODE_CBC, md5(md5($key))), "\0"));
 return $s;
}

Es flexible, ya que puede almacenar/enviar a través de URL una cadena o matriz porque la cadena/matriz se serializa antes del cifrado.

 3
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-15 08:16:56

Esto solo le dará una protección marginal. Si el atacante puede ejecutar código arbitrario en su aplicación, puede obtener las contraseñas exactamente de la misma manera que su aplicación puede. Todavía podría obtener cierta protección contra algunos ataques de inyección SQL y copias de seguridad de bases de datos extraviadas si almacena una clave secreta en un archivo y la usa para cifrar en el camino a la base de datos y descifrar en la salida. Pero debe usar bindparams para evitar completamente el problema de la inyección SQL.

Si decide encrypt, debe usar alguna biblioteca de cifrado de alto nivel para esto, o se equivocará. Tendrá que corregir la configuración de la clave, el relleno del mensaje y las comprobaciones de integridad, o todo su esfuerzo de cifrado será de poca utilidad. GPGME es una buena opción para un ejemplo. Mcrypt es demasiado bajo nivel y es probable que se equivoque.

 2
Author: Ants Aasma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-17 16:53:45

Echa un vistazo a mycrypt (): http://us.php.net/manual/en/book.mcrypt.php

Y si estás usando postgres está pgcrypto para el cifrado a nivel de base de datos. (hace que sea más fácil buscar y ordenar)

 1
Author: Josh Rice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-17 16:50:59

La mejor idea para cifrar/descifrar sus datos en la base de datos incluso si tiene acceso al código es usar 2 pases diferentes una contraseña privada (user-pass) para cada usuario y un código privado para todos los usuarios (system-pass).

Hipótesis

  1. user-pass se almacena con md5 en la base de datos y se utiliza para validar que cada usuario inicie sesión en el sistema. Este pase de usuario es diferente para cada usuario.
  2. Cada entrada de usuario en la base de datos tiene en md5 un system-pass para el cifrado/descifrado de los datos. Este system-pass es el mismo para cada usuario.
  3. Cada vez que un usuario está siendo eliminado del sistema, todos los datos que están encriptados bajo el antiguo system-pass deben ser encriptados nuevamente bajo un nuevo system-pass para evitar problemas de seguridad.
 0
Author: Nikos Tsirakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-18 15:19:24