La mcrypt-extensión es obsoleto será eliminado en PHP 7.2 de acuerdo con el comentario publicado aquí. Así que estoy buscando una forma alternativa para cifrar las contraseñas.

Ahora mismo estoy usando algo como

mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key, true), $string, MCRYPT_MODE_CBC, $iv)

Necesito su opinión para la mejor/más fuerte forma de cifrar las contraseñas, la contraseña cifrada debe, por supuesto, soportadas por PHP 7.xx, y también debe ser decryptable porque mis clientes que quieren tener una opción para ‘recuperar’ sus contraseñas sin generar una nueva.

Por qué usted necesita para cifrar/descifrar las contraseñas? ¿Por qué no acaba de hash con password_hash y verificar con password_verify?
«la contraseña cifrada también debe ser decryptable» – ¿por qué? no suena demasiado fuerte. Alguna razón en especial?
«debido a que mis clientes quieren tener la opción para ‘recuperar’ sus contraseñas sin generar uno nuevo.» – Que no es seguro y se les debe dar la opción para restablecer sus contraseñas en su lugar.
no cifrar las contraseñas, cuando el atacante obtiene el DB él también va a obtener la clave de cifrado. Iterar a través de un HMAC con una muestra aleatoria de sal durante aproximadamente un 100 ms de duración y guardar la sal con el hash. Utilizar funciones tales como password_hash, PBKDF2, Bcrypt y funciones similares. El punto es hacer que el atacante pasar mucho tiempo para encontrar las contraseñas por fuerza bruta.
Desde el manual de php -> Esta función ha quedado OBSOLETA a partir de PHP 7.1.0. Apoyándose en esta función es sumamente desalentador. La alternativa es el sodio -> php.net/manual/en/book.sodium.php

OriginalEl autor Piet | 2016-12-21

8 Comentarios

  1. 31

    Es la mejor práctica para los hash de las contraseñas para que no decryptable. Esto hace las cosas un poco más difícil para los atacantes que pueden haber obtenido acceso a su base de datos o archivos.

    Si debe cifrar sus datos y que se decryptable, una guía de seguro de cifrado/descifrado está disponible en https://paragonie.com/white-paper/2015-secure-php-data-encryption. Para resumir que enlace:

    • Uso Libsodium – UNA extensión de PHP
    • Si usted no puede utilizar Libsodium, uso desactivar/php-cifrado Recta de código PHP
    • Si usted no puede utilizar Libsodium o desactivar/php-cifrado, uso OpenSSL – Un montón de servidores ya lo tienen instalado. Si no, puede ser compilado con la opción –with-openssl[=DIR]
    Voy a echar un vistazo a estas opciones, gracias por la respuesta y gracias a todos por la respuesta!
    Primero debe tratar de openssl, ya que es muy común, donde libsodium no lo es. Raw php no debe ser utilizado a menos que todos los nativos de extensión se si la pregunta
    aunque openssl es muy común, parece que php 7 va a ser el uso de libsodium por su centro de criptografía securityintelligence.com/news/…
    Lo abt datos antiguos que ya está cifrada en PHP 5.3??
    Nota: hay una librería llamada Sodium-compat (github.com/paragonie/sodium_compat), que funciona en PHP >= 5.2.4

    OriginalEl autor Phil

  2. 15

    Según lo sugerido por @rqLizard, puede utilizar openssl_encrypt/openssl_decrypt de las funciones de PHP, el cual proporciona una
    la mejor alternativa para implementar AES (Estándar de Cifrado Avanzado), también conocido como Rijndael de cifrado.

    Por el siguiente Scott comentario en php.net:

    Si estás escribiendo código para cifrar o encriptar los datos en el año 2015, debe utilizar openssl_encrypt() y openssl_decrypt(). La biblioteca subyacente (libmcrypt) ha sido abandonada desde 2007, y realiza mucho peor que OpenSSL (que aprovecha AES-NI en los procesadores modernos y es la memoria caché de temporización de seguro).

    También, MCRYPT_RIJNDAEL_256 no es AES-256, es otra variante de la Rijndael de cifrado de bloque. Si desea AES-256 en mcrypt, usted tiene que utilizar MCRYPT_RIJNDAEL_128 con 32 bytes de la clave. OpenSSL hace más evidente el modo en que usted está utilizando (es decir, aes-128-cbc vs aes-256-ctr).

    OpenSSL también utiliza relleno de PKCS7 con el modo CBC en lugar de mcrypt NULL bytes de relleno. Por lo tanto, mcrypt es más probable que el código vulnerable a padding oracle ataques de OpenSSL.

    Finalmente, si no se la autenticación de su ciphertexts (Cifrar, a Continuación, MAC), lo estás haciendo mal.

    Leer más:

    Ejemplos de código

    Ejemplo #1

    AES de Cifrado Autenticado en GCM modo de ejemplo para PHP 7.1+

    <?php
    //$key should have been previously generated in a cryptographically safe way, like openssl_random_pseudo_bytes
    $plaintext = "message to be encrypted";
    $cipher = "aes-128-gcm";
    if (in_array($cipher, openssl_get_cipher_methods()))
    {
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag);
        //store $cipher, $iv, and $tag for decryption later
        $original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag);
        echo $original_plaintext."\n";
    }
    ?>

    Ejemplo #2

    AES de Cifrado Autenticado ejemplo de PHP 5.6+

    <?php
    //$key previously generated safely, ie: openssl_random_pseudo_bytes
    $plaintext = "message to be encrypted";
    $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
    $iv = openssl_random_pseudo_bytes($ivlen);
    $ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
    $hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
    $ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
    
    //decrypt later....
    $c = base64_decode($ciphertext);
    $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
    $iv = substr($c, 0, $ivlen);
    $hmac = substr($c, $ivlen, $sha2len=32);
    $ciphertext_raw = substr($c, $ivlen+$sha2len);
    $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
    $calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
    if (hash_equals($hmac, $calcmac))//PHP 5.6+ timing attack safe comparison
    {
        echo $original_plaintext."\n";
    }
    ?>

    Ejemplo #3

    Basado en ejemplos anteriores, he cambiado el código siguiente, que tiene como objetivo el cifrado de sesión del usuario id:

    class Session {
    
      /**
       * Encrypts the session ID and returns it as a base 64 encoded string.
       *
       * @param $session_id
       * @return string
       */
      public function encrypt($session_id) {
        //Get the MD5 hash salt as a key.
        $key = $this->_getSalt();
        //For an easy iv, MD5 the salt again.
        $iv = $this->_getIv();
        //Encrypt the session ID.
        $encrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $session_id, MCRYPT_MODE_CBC, $iv);
        //Base 64 encode the encrypted session ID.
        $encryptedSessionId = base64_encode($encrypt);
        //Return it.
        return $encryptedSessionId;
      }
    
      /**
       * Decrypts a base 64 encoded encrypted session ID back to its original form.
       *
       * @param $encryptedSessionId
       * @return string
       */
      public function decrypt($encryptedSessionId) {
        //Get the MD5 hash salt as a key.
        $key = $this->_getSalt();
        //For an easy iv, MD5 the salt again.
        $iv = $this->_getIv();
        //Decode the encrypted session ID from base 64.
        $decoded = base64_decode($encryptedSessionId);
        //Decrypt the string.
        $decryptedSessionId = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $decoded, MCRYPT_MODE_CBC, $iv);
        //Trim the whitespace from the end.
        $session_id = rtrim($decryptedSessionId, "
    class Session {
    /**
    * Encrypts the session ID and returns it as a base 64 encoded string.
    *
    * @param $session_id
    * @return string
    */
    public function encrypt($session_id) {
    //Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    //For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    //Encrypt the session ID.
    $encrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $session_id, MCRYPT_MODE_CBC, $iv);
    //Base 64 encode the encrypted session ID.
    $encryptedSessionId = base64_encode($encrypt);
    //Return it.
    return $encryptedSessionId;
    }
    /**
    * Decrypts a base 64 encoded encrypted session ID back to its original form.
    *
    * @param $encryptedSessionId
    * @return string
    */
    public function decrypt($encryptedSessionId) {
    //Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    //For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    //Decode the encrypted session ID from base 64.
    $decoded = base64_decode($encryptedSessionId);
    //Decrypt the string.
    $decryptedSessionId = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $decoded, MCRYPT_MODE_CBC, $iv);
    //Trim the whitespace from the end.
    $session_id = rtrim($decryptedSessionId, "\0");
    //Return it.
    return $session_id;
    }
    public function _getIv() {
    return md5($this->_getSalt());
    }
    public function _getSalt() {
    return md5($this->drupal->drupalGetHashSalt());
    }
    }
    "
    ); //Return it. return $session_id; } public function _getIv() { return md5($this->_getSalt()); } public function _getSalt() { return md5($this->drupal->drupalGetHashSalt()); } }

    en:

    class Session {
    
      const SESS_CIPHER = 'aes-128-cbc';
    
      /**
       * Encrypts the session ID and returns it as a base 64 encoded string.
       *
       * @param $session_id
       * @return string
       */
      public function encrypt($session_id) {
        //Get the MD5 hash salt as a key.
        $key = $this->_getSalt();
        //For an easy iv, MD5 the salt again.
        $iv = $this->_getIv();
        //Encrypt the session ID.
        $ciphertext = openssl_encrypt($session_id, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
        //Base 64 encode the encrypted session ID.
        $encryptedSessionId = base64_encode($ciphertext);
        //Return it.
        return $encryptedSessionId;
      }
    
      /**
       * Decrypts a base 64 encoded encrypted session ID back to its original form.
       *
       * @param $encryptedSessionId
       * @return string
       */
      public function decrypt($encryptedSessionId) {
        //Get the Drupal hash salt as a key.
        $key = $this->_getSalt();
        //Get the iv.
        $iv = $this->_getIv();
        //Decode the encrypted session ID from base 64.
        $decoded = base64_decode($encryptedSessionId, TRUE);
        //Decrypt the string.
        $decryptedSessionId = openssl_decrypt($decoded, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
        //Trim the whitespace from the end.
        $session_id = rtrim($decryptedSessionId, '
    class Session {
    const SESS_CIPHER = 'aes-128-cbc';
    /**
    * Encrypts the session ID and returns it as a base 64 encoded string.
    *
    * @param $session_id
    * @return string
    */
    public function encrypt($session_id) {
    //Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    //For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    //Encrypt the session ID.
    $ciphertext = openssl_encrypt($session_id, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
    //Base 64 encode the encrypted session ID.
    $encryptedSessionId = base64_encode($ciphertext);
    //Return it.
    return $encryptedSessionId;
    }
    /**
    * Decrypts a base 64 encoded encrypted session ID back to its original form.
    *
    * @param $encryptedSessionId
    * @return string
    */
    public function decrypt($encryptedSessionId) {
    //Get the Drupal hash salt as a key.
    $key = $this->_getSalt();
    //Get the iv.
    $iv = $this->_getIv();
    //Decode the encrypted session ID from base 64.
    $decoded = base64_decode($encryptedSessionId, TRUE);
    //Decrypt the string.
    $decryptedSessionId = openssl_decrypt($decoded, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
    //Trim the whitespace from the end.
    $session_id = rtrim($decryptedSessionId, '\0');
    //Return it.
    return $session_id;
    }
    public function _getIv() {
    $ivlen = openssl_cipher_iv_length(self::SESS_CIPHER);
    return substr(md5($this->_getSalt()), 0, $ivlen);
    }
    public function _getSalt() {
    return $this->drupal->drupalGetHashSalt();
    }
    }
    '
    ); //Return it. return $session_id; } public function _getIv() { $ivlen = openssl_cipher_iv_length(self::SESS_CIPHER); return substr(md5($this->_getSalt()), 0, $ivlen); } public function _getSalt() { return $this->drupal->drupalGetHashSalt(); } }

    Para aclarar, por encima de cambio no es una verdadera conversión, ya que los dos cifrado utiliza un tamaño de bloque distinto y diferente a los datos cifrados. Además, el relleno predeterminado es diferente, MCRYPT_RIJNDAEL sólo apoya la no-nula estándar de relleno. @zaph


    Notas adicionales (a partir de la @zaph comentarios):

    • Rijndael de 128 (MCRYPT_RIJNDAEL_128) es equivalente a AES, sin embargo Rijndael de 256 (MCRYPT_RIJNDAEL_256) no es AES-256 como la de 256 especifica un tamaño de bloque de 256-bits, mientras que AES sólo tiene un tamaño de bloque: 128-bits. Así que, básicamente, Rijndael con un tamaño de bloque de 256-bits (MCRYPT_RIJNDAEL_256) ha sido erróneamente llamada así debido a las decisiones de la mcrypt los desarrolladores. @zaph
    • Rijndael con un tamaño de bloque de 256 puede ser menos seguro que con un tamaño de bloque de 128 bits, dado que este último ha tenido mucho más los comentarios y los usos. En segundo lugar, la interoperabilidad es obstaculizado en que mientras que AES es generalmente disponible, donde Rijndael con un tamaño de bloque de 256-bits no está.
    • Cifrado con diferentes tamaños de bloque para Rijndael produce diferentes datos cifrados.

      Por ejemplo, MCRYPT_RIJNDAEL_256 (no equivalente a AES-256) define diferentes variantes de la Rijndael de cifrado de bloques con un tamaño de 256 bits y una clave de tamaño basado en el pasado en clave, donde aes-256-cbc es Rijndael con un tamaño de bloque de 128-bits con un tamaño de clave de 256-bits. Por lo tanto están utilizando diferentes tamaños de bloque que produce totalmente diferente cifrado de datos como mcrypt usa el número para especificar el tamaño del bloque, donde OpenSSL utilizar el número para especificar el tamaño de la clave (AES sólo tiene un tamaño de bloque de 128 bits). Así que, básicamente, AES Rijndael con un tamaño de bloque de 128 bits y tamaños de clave de 128, 192 y 256 bits. Por lo tanto es mejor utilizar AES, que se llama Rijndael de 128 en OpenSSL.

    En general el uso de Rijndael con un tamaño de bloque de 256-bits es un error debido a las decisiones por el mcrypt los desarrolladores. Más Rijndael con un tamaño de bloque de 256 puede ser menos seguro que con un tamaño de bloque de 128 bits, dado que este último ha tenido mucho más revisión y uso. Además, la interoperabilidad es obstaculizado en que mientras que AES es generalmente disponible Rijndael con un tamaño de bloque de 256-bits no está.

    OriginalEl autor kenorb

  3. 2

    Puede utilizar phpseclib pollyfill paquete. Usted no puede utilizar el open ssl o libsodium para cifrar/descifrar con rijndael de 256.
    Otro problema, no es necesario cambiar ningún código.

    OriginalEl autor Ahmet Erkan ÇELİK

  4. 1

    Como se señaló, no se debe almacenar tus contraseñas de usuario en un formato que es decryptable. Reversable de cifrado proporciona una ruta fácil para los hackers para averiguar sus contraseñas de usuario, que se extiende a poner las cuentas de los usuarios a otros sitios en riesgo en caso de que se utilice la misma contraseña.

    PHP proporciona un par de funciones de gran alcance para el azar-salado, one-way hash cifrado password_hash() y password_verify(). Debido a que el hash es automáticamente al azar salada, no hay manera de que los hackers utilizan precompilado tablas de hash de contraseña para revertir la ingeniería de la contraseña. Establecer el PASSWORD_DEFAULT opción y futuras versiones de PHP automáticamente el uso de algoritmos más fuertes para generar hashes de las contraseñas sin tener que actualizar el código.

    OriginalEl autor Thoracius Appotite

  5. 1

    Debe utilizar openssl_encrypt() función.

    Son los openssl cifrar en php 7 la «heartbleed» ?
    ¿por qué debe el OP utilizar openssl_encrypt? Dar algunos detalles y el fondo

    OriginalEl autor rqLizard

  6. 0

    Yo era capaz de traducir mi Crypto objeto

    • Obtener una copia de php con mcrypt para descifrar los datos antiguos. Fui a http://php.net/get/php-7.1.12.tar.gz/from/a/mirror, compiló, agregó el ext/extensión mcrypt (configure;make;make install). Creo que tuve que agregar el extenstion=mcrypt.así que la línea para el php.ini así. Una serie de scripts para construir las versiones intermedias de los datos con todos los datos sin cifrar.

    • Construir una clave pública y privada para openssl

      openssl genrsa -des3 -out pkey.pem 2048
      (set a password)
      openssl rsa -in pkey.pem -out pkey-pub.pem -outform PEM -pubout
    • Para Cifrar (mediante clave pública) uso openssl_seal. Por lo que he leído, openssl_encrypt el uso de una clave RSA está limitado a 11 bytes menor que la longitud de la clave (Ver http://php.net/manual/en/function.openssl-public-encrypt.php comentario por Thomas Horsten)

      $pubKey = openssl_get_publickey(file_get_contents('./pkey-pub.pem'));
      openssl_seal($pwd, $sealed, $ekeys, [ $pubKey ]);
      $encryptedPassword = base64_encode($sealed);
      $key = base64_encode($ekeys[0]);

    Probablemente se podría almacenar el binario.

    • Para Descifrar (usando la clave privada)

      $passphrase="passphrase here";
      $privKey = openssl_get_privatekey(file_get_contents('./pkey.pem'), $passphrase);
      //I base64_decode() from my db columns
      openssl_open($encryptedPassword, $plain, $key, $privKey);
      echo "<h3>Password=$plain</h3>";

    P. S. no Se puede cifrar la cadena vacía («»)

    P. P. S. Esta es una contraseña de base de datos no para la validación de usuario.

    OriginalEl autor Joshua Goldstein

  7. 0

    Debe usar OpenSSL más de mcrypt como es activamente desarrollado y mantenido. Proporciona mejor seguridad, mantenibilidad y portabilidad. En segundo lugar, se realiza AES de cifrado/descifrado mucho más rápido. Se utiliza relleno de PKCS7 por defecto, pero usted puede especificar OPENSSL_ZERO_PADDING si la necesita. Para utilizar con 32 bytes de claves binarias, usted puede especificar aes-256-cbc que es mucho evidente que MCRYPT_RIJNDAEL_128.

    Aquí está el código de ejemplo de uso de Mcrypt:

    No autenticado AES-256-CBC de la biblioteca de cifrado escrito en Mcrypt con relleno de PKCS7.

    /**
    * This library is unsafe because it does not MAC after encrypting
    */
    class UnsafeMcryptAES
    {
    const CIPHER = MCRYPT_RIJNDAEL_128;
    public static function encrypt($message, $key)
    {
    if (mb_strlen($key, '8bit') !== 32) {
    throw new Exception("Needs a 256-bit key!");
    }
    $ivsize = mcrypt_get_iv_size(self::CIPHER);
    $iv = mcrypt_create_iv($ivsize, MCRYPT_DEV_URANDOM);
    //Add PKCS7 Padding
    $block = mcrypt_get_block_size(self::CIPHER);
    $pad = $block - (mb_strlen($message, '8bit') % $block, '8bit');
    $message .= str_repeat(chr($pad), $pad);
    $ciphertext = mcrypt_encrypt(
    MCRYPT_RIJNDAEL_128,
    $key,
    $message,
    MCRYPT_MODE_CBC,
    $iv
    );
    return $iv . $ciphertext;
    }
    public static function decrypt($message, $key)
    {
    if (mb_strlen($key, '8bit') !== 32) {
    throw new Exception("Needs a 256-bit key!");
    }
    $ivsize = mcrypt_get_iv_size(self::CIPHER);
    $iv = mb_substr($message, 0, $ivsize, '8bit');
    $ciphertext = mb_substr($message, $ivsize, null, '8bit');
    $plaintext = mcrypt_decrypt(
    MCRYPT_RIJNDAEL_128,
    $key,
    $ciphertext,
    MCRYPT_MODE_CBC,
    $iv
    );
    $len = mb_strlen($plaintext, '8bit');
    $pad = ord($plaintext[$len - 1]);
    if ($pad <= 0 || $pad > $block) {
    //Padding error!
    return false;
    }
    return mb_substr($plaintext, 0, $len - $pad, '8bit');
    }
    }

    Y aquí está la versión escrita con OpenSSL:

    /**
    * This library is unsafe because it does not MAC after encrypting
    */
    class UnsafeOpensslAES
    {
    const METHOD = 'aes-256-cbc';
    public static function encrypt($message, $key)
    {
    if (mb_strlen($key, '8bit') !== 32) {
    throw new Exception("Needs a 256-bit key!");
    }
    $ivsize = openssl_cipher_iv_length(self::METHOD);
    $iv = openssl_random_pseudo_bytes($ivsize);
    $ciphertext = openssl_encrypt(
    $message,
    self::METHOD,
    $key,
    OPENSSL_RAW_DATA,
    $iv
    );
    return $iv . $ciphertext;
    }
    public static function decrypt($message, $key)
    {
    if (mb_strlen($key, '8bit') !== 32) {
    throw new Exception("Needs a 256-bit key!");
    }
    $ivsize = openssl_cipher_iv_length(self::METHOD);
    $iv = mb_substr($message, 0, $ivsize, '8bit');
    $ciphertext = mb_substr($message, $ivsize, null, '8bit');
    return openssl_decrypt(
    $ciphertext,
    self::METHOD,
    $key,
    OPENSSL_RAW_DATA,
    $iv
    );
    }
    }

    Fuente: Si Usted está Escribiendo la Palabra MCRYPT En Tu Código PHP, Lo estás Haciendo Mal.

    OriginalEl autor kenorb

  8. -2

    Solo uso @ antes de cada mcrypt por ejemplo:

    @mcrypt_module_open,
    @mcrypt_get_block_size,
    @mcrypt_generic_init
    @mcrypt_generic
    @mcrypt_generic_deinit

    Va a quitar la función de mcrypt_module_open depriciated error y trabajo.

    No funciona en el apartado 7.2.x o más reciente, mcrypt fue eliminado.

    OriginalEl autor rocky sharma

Dejar respuesta

Please enter your comment!
Please enter your name here