password pass encriptar encriptada desencriptar contraseñas contraseña con php security encryption cryptography encryption-symmetric

pass - login con contraseña encriptada php



¿Cómo encriptas y descifras una cadena de PHP? (5)

Lo que quiero decir es:

Original String + Salt or Key --> Encrypted String Encrypted String + Salt or Key --> Decrypted (Original String)

Tal vez algo así como:

"hello world!" + "ABCD1234" --> Encrypt --> "2a2ffa8f13220befbe30819047e23b2c" (may be, for e.g) "2a2ffa8f13220befbe30819047e23b2c" --> Decrypt with "ABCD1234" --> "hello world!"

  • En PHP, ¿cómo puedes hacer esto?

Crypt_Blowfish usar Crypt_Blowfish , pero no funcionó para mí.


Nota histórica: Esto fue escrito en el momento de PHP4. Esto es lo que llamamos "código heredado" ahora.

He dejado esta respuesta por razones históricas, pero algunos de los métodos están en desuso, el método de cifrado DES no es una práctica recomendada, etc.

No he actualizado este código por dos razones: 1) Ya no trabajo con métodos de encriptación a mano en PHP, y 2) este código aún cumple con el propósito para el que estaba destinado: demostrar el concepto mínimo y simplista de cómo puede funcionar el cifrado en PHP.

Si encuentra un tipo de fuente igualmente simplista, "encriptación PHP para tontos" que puede hacer que las personas comiencen en 10-20 líneas de código o menos, háganmelo saber en los comentarios.

Más allá de eso, disfruta de este episodio clásico de la respuesta de cifrado minimalista PHP4 de la era temprana.

Lo ideal es que tenga, o pueda acceder, a la biblioteca PHP de mcrypt, ya que es ciertamente popular y muy útil para una variedad de tareas. A continuación se detallan los diferentes tipos de cifrado y algunos códigos de ejemplo: Técnicas de encriptación en PHP

//Listing 3: Encrypting Data Using the mcrypt_ecb Function <?php echo("<h3> Symmetric Encryption </h3>"); $key_value = "KEYVALUE"; $plain_text = "PLAINTEXT"; $encrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $plain_text, MCRYPT_ENCRYPT); echo ("<p><b> Text after encryption : </b>"); echo ( $encrypted_text ); $decrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $encrypted_text, MCRYPT_DECRYPT); echo ("<p><b> Text after decryption : </b>"); echo ( $decrypted_text ); ?>

Algunas advertencias:

1) Nunca use cifrado reversible o "simétrico" cuando lo haga un hash unidireccional.

2) Si la información es realmente confidencial, como números de tarjeta de crédito o de seguridad social, deténgase; necesita más de lo que proporcionará un simple trozo de código, pero necesita una biblioteca criptográfica diseñada para este fin y una cantidad de tiempo considerable para investigar los métodos necesarios. Además, el software crypto es probablemente <10% de seguridad de datos confidenciales. Es como volver a cablear una estación de energía nuclear: acepte que la tarea es peligrosa y difícil y más allá de su conocimiento si ese es el caso. Las sanciones financieras pueden ser inmensas, así que es mejor usar un servicio y enviarles la responsabilidad.

3) Cualquier tipo de encriptación fácilmente implementable, como se detalla aquí, puede proteger de manera razonable la información levemente importante que desea evitar de miradas indiscretas o limitar la exposición en el caso de una fuga accidental / intencional. Pero al ver cómo se almacena la clave en texto plano en el servidor web, si pueden obtener los datos, pueden obtener la clave de descifrado.

Sea como sea, diviértete :)


Para el marco de Laravel

Si está utilizando el marco de Laravel, entonces es más fácil de cifrar y descifrar con funciones internas.

$string = ''Some text to be encrypted''; $encrypted = /Illuminate/Support/Facades/Crypt::encrypt($string); $decrypted_string = /Illuminate/Support/Facades/Crypt::decrypt($encrypted); var_dump($string); var_dump($encrypted); var_dump($decrypted_string);

Nota: asegúrese de establecer una cadena aleatoria de 16, 24 o 32 caracteres en la opción clave del archivo config / app.php. De lo contrario, los valores cifrados no serán seguros.


Antes de hacer algo más, intente comprender la diferencia entre el cifrado y la autenticación , y por qué probablemente desea un cifrado autenticado en lugar de solo cifrado .

Para implementar el cifrado autenticado, desea cifrar y luego MAC. ¡El orden de encriptación y autenticación es muy importante! Una de las respuestas existentes a esta pregunta cometió este error; como lo hacen muchas bibliotecas de criptografía escritas en PHP.

Debe evitar implementar su propia criptografía y, en su lugar, usar una biblioteca segura escrita y revisada por expertos en criptografía.

Actualización: ¡PHP 7.2 ahora proporciona libsodium ! Actualizado a PHP 7.2 o superior y solo siga los consejos de libsodium en esta respuesta.

Utilice libsodium si tiene acceso PECL (o sodium_compat si quiere libsodium sin PECL); de otra manera...
Use defuse / php-encryption ; ¡no hagas tu propia criptografía!

Ambas bibliotecas, vinculadas anteriormente, facilitan e implementan el cifrado autenticado en sus propias bibliotecas.

Si aún desea escribir y desplegar su propia biblioteca de criptografía, contra la sabiduría convencional de cada experto en criptografía en Internet, estos son los pasos que debe seguir.

Cifrado:

  1. Cifre usando AES en modo CTR. También puede usar GCM (que elimina la necesidad de un MAC por separado). Además, ChaCha20 y Salsa20 (proporcionados por libsodium ) son sistemas de cifrado de flujo y no necesitan modos especiales.
  2. A menos que haya elegido GCM arriba, debe autenticar el texto cifrado con HMAC-SHA-256 (o, para los códigos de flujo, Poly1305, la mayoría de las API de Libsodium lo hacen por usted). ¡El MAC debería cubrir el IV así como el texto cifrado!

Descifrado:

  1. A menos que se utilice Poly1305 o GCM, vuelva a calcular el MAC del texto cifrado y compárelo con el MAC que se envió utilizando hash_equals() . Si falla, aborta.
  2. Descifrar el mensaje

Otras consideraciones de diseño:

  1. No compres nada nunca. El texto cifrado no es compresible; la compresión de texto sin formato antes del cifrado puede generar filtraciones de información (por ejemplo, CRIMEN y INCUMPLIMIENTO en TLS).
  2. Asegúrese de utilizar mb_strlen() y mb_substr() , utilizando el modo de juego de caracteres ''8bit'' para evitar problemas de mbstring.func_overload .
  3. IVs debe generar usando un CSPRNG ; Si está utilizando mcrypt_create_iv() , ¡NO USE MCRYPT_RAND !
  4. ¡A menos que estés usando una construcción AEAD, SIEMPRE encripta entonces MAC!
  5. bin2hex() , base64_encode() , etc. pueden perder información sobre sus claves de cifrado a través del tiempo de caché. Evítalos si es posible.

Incluso si sigue los consejos dados aquí, muchas cosas pueden salir mal con la criptografía. Siempre haga que un experto en criptografía revise su implementación. Si no tiene la suerte de ser amigo personal de un estudiante de criptografía en su universidad local, siempre puede probar el foro de Cryptography Stack Exchange para obtener consejos.

Si necesita un análisis profesional de su implementación, siempre puede contratar un equipo acreditado de consultores de seguridad para revisar su código de criptografía PHP (divulgación: mi empleador).

Importante: cuándo no usar el cifrado

No cifre las contraseñas . En su lugar, quiere usar hash , utilizando uno de estos algoritmos hash de contraseñas:

Nunca use una función hash de propósito general (MD5, SHA256) para el almacenamiento de contraseñas.

No cifre los parámetros de URL . Es la herramienta incorrecta para el trabajo.

Ejemplo de cifrado de cadenas PHP con Libsodium

Si está en PHP <7.2 o no tiene instalado libsodium, puede usar sodium_compat para lograr el mismo resultado (aunque más lento).

<?php declare(strict_types=1); /** * Encrypt a message * * @param string $message - message to encrypt * @param string $key - encryption key * @return string * @throws RangeException */ function safeEncrypt(string $message, string $key): string { if (mb_strlen($key, ''8bit'') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { throw new RangeException(''Key is not he correct size (must be 32 bytes).''); } $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $cipher = base64_encode( $nonce. sodium_crypto_secretbox( $message, $nonce, $key ) ); sodium_memzero($message); sodium_memzero($key); return $cipher; } /** * Decrypt a message * * @param string $encrypted - message encrypted with safeEncrypt() * @param string $key - encryption key * @return string * @throws Exception */ function safeDecrypt(string $encrypted, string $key): string { $decoded = base64_decode($encrypted); $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, ''8bit''); $ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, ''8bit''); $plain = sodium_crypto_secretbox_open( $ciphertext, $nonce, $key ); if (!is_string($plain)) { throw new Exception(''Invalid MAC''); } sodium_memzero($ciphertext); sodium_memzero($key); return $plain; }

Luego para probarlo:

<?php // This refers to the previous code block. require "safeCrypto.php"; // Do this once then store it somehow: $key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES); $message = ''We are all living in a yellow submarine''; $ciphertext = safeEncrypt($message, $key); $plaintext = safeDecrypt($ciphertext, $key); var_dump($ciphertext); var_dump($plaintext);

Halite - Libsodium se hizo más fácil

Uno de los proyectos en los que he estado trabajando es una biblioteca de cifrado llamada Halite , que tiene como objetivo hacer que Libsodium sea más fácil e intuitivo.

<?php use /ParagonIE/Halite/KeyFactory; use /ParagonIE/Halite/Symmetric/Crypto as SymmetricCrypto; // Generate a new random symmetric-key encryption key. You''re going to want to store this: $key = new KeyFactory::generateEncryptionKey(); // To save your encryption key: KeyFactory::save($key, ''/path/to/secret.key''); // To load it again: $loadedkey = KeyFactory::loadEncryptionKey(''/path/to/secret.key''); $message = ''We are all living in a yellow submarine''; $ciphertext = SymmetricCrypto::encrypt($message, $key); $plaintext = SymmetricCrypto::decrypt($ciphertext, $key); var_dump($ciphertext); var_dump($plaintext);

Toda la criptografía subyacente es manejada por libsodium.

Ejemplo con defuse / php-encryption

<?php /** * This requires https://github.com/defuse/php-encryption * php composer.phar require defuse/php-encryption */ use Defuse/Crypto/Crypto; use Defuse/Crypto/Key; require "vendor/autoload.php"; // Do this once then store it somehow: $key = Key::createNewRandomKey(); $message = ''We are all living in a yellow submarine''; $ciphertext = Crypto::encrypt($message, $key); $plaintext = Crypto::decrypt($ciphertext, $key); var_dump($ciphertext); var_dump($plaintext);

Nota : Crypto::encrypt() devuelve salida codificada en hexadecimal.

Gestión de clave de cifrado

Si está tentado de usar una "contraseña", deténgase ahora mismo. Necesita una clave de cifrado aleatoria de 128 bits, no una contraseña memorable para el ser humano.

Puede almacenar una clave de cifrado para un uso a largo plazo como ese:

$storeMe = bin2hex($key);

Y, bajo demanda, puede recuperarlo así:

$key = hex2bin($storeMe);

Recomiendo simplemente almacenar una clave generada aleatoriamente para uso a largo plazo en lugar de cualquier tipo de contraseña como la clave (o para derivar la clave).

Si está utilizando la biblioteca de Defuse:

"Pero realmente quiero usar una contraseña".

Esa es una mala idea, pero está bien, así es cómo hacerlo de manera segura.

Primero, genere una clave aleatoria y guárdela en una constante.

/** * Replace this with your own salt! * Use bin2hex() then add /x before every 2 hex characters, like so: */ define(''MY_PBKDF2_SALT'', "/x2d/xb7/x68/x1a/x28/x15/xbe/x06/x33/xa0/x7e/x0e/x8f/x79/xd5/xdf");

Tenga en cuenta que está agregando trabajo adicional y podría usar esta constante como la clave y ahorrarse un montón de dolor.

Luego use PBKDF2 (como tal) para derivar una clave de cifrado adecuada de su contraseña en lugar de cifrar con su contraseña directamente.

/** * Get an AES key from a static password and a secret salt * * @param string $password Your weak password here * @param int $keysize Number of bytes in encryption key */ function getKeyFromPassword($password, $keysize = 16) { return hash_pbkdf2( ''sha256'', $password, MY_PBKDF2_SALT, 100000, // Number of iterations $keysize, true ); }

No use solo una contraseña de 16 caracteres. Su clave de cifrado se romperá cómicamente.


Llego tarde a la fiesta, pero al buscar la forma correcta de hacerlo, encontré esta página que era una de las principales devoluciones de búsqueda de Google, así que me gustaría compartir mi opinión sobre el problema, que considero que es actualizado al momento de escribir esta publicación (a partir de 2017). De PHP 7.1.0 el mcrypt_decrypt y mcrypt_encrypt van a estar en desuso, por lo que la construcción de un código de prueba futuro debería usar openssl_encrypt y openssl_decrypt

Puedes hacer algo como:

$string_to_encrypt="Test"; $password="password"; $encrypted_string=openssl_encrypt($string_to_encrypt,"AES-128-ECB",$password); $decrypted_string=openssl_decrypt($encrypted_string,"AES-128-ECB",$password);

Importante : Esto usa el modo ECB , que no es seguro. Si desea una solución simple sin tomar un curso acelerado en ingeniería de criptografía, no la escriba usted mismo, solo use una biblioteca .

También puede usar cualquier otro método de astilladora, según sus necesidades de seguridad. Para conocer los métodos de astillamiento disponibles, consulte la función openssl_get_cipher_methods .


Qué no hacer

ADVERTENCIA:
Esta respuesta usa ECB . ECB no es un modo de encriptación, es solo un bloque de construcción. Usar ECB como se demuestra en esta respuesta no encripta la cadena de forma segura. No use ECB en su código. Vea share para una buena solución.

Lo tengo yo mismo. De hecho, encontré algunas respuestas en google y simplemente modifiqué algo. El resultado es completamente inseguro sin embargo.

<?php define("ENCRYPTION_KEY", "!@#$%^&*"); $string = "This is the original data string!"; echo $encrypted = encrypt($string, ENCRYPTION_KEY); echo "<br />"; echo $decrypted = decrypt($encrypted, ENCRYPTION_KEY); /** * Returns an encrypted & utf8-encoded */ function encrypt($pure_string, $encryption_key) { $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv); return $encrypted_string; } /** * Returns decrypted original string */ function decrypt($encrypted_string, $encryption_key) { $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv); return $decrypted_string; } ?>