2010-07-17 21 views
10

Como la mayoría de los usuarios, simplemente intento encontrar una forma segura de almacenar contraseñas. Lo que no he encontrado aquí (o tal vez es mi falta de comprensión) es cómo recuperar un hash salado en mi base de datos y separar la sal de la contraseña hash, especialmente con sales únicas para cada contraseña mientras se mantiene la contraseña sal + en una sola columnaSalting my hashes con PHP y MySQL

estoy encontrando todas estas maneras frescas para cifrar contraseñas (SHA-256, pero ¿MySQL sólo el apoyo de SHA/1 y MD5?) Y otras cosas del manual de PHP, pero no sabe cómo almacenar y recuperar las contraseñas.

Por lo tanto, ahora esto es todo lo entiendo:

SHA('$salt'.'$password') // My query sends the password and salt 
         // (Should the $salt be a hash itself?) 

Después de eso estoy perdido con sales.

Recuperar la contraseña sin sal es fácil, pero la sal me confunde. ¿De dónde saco el valor de $ salt nuevamente, especialmente si es único y seguro? ¿Los escondo en otra base de datos? Constante (parece inseguro)?

EDIT: ¿Se supone que la variable clave en HMAC es sal o es otra cosa?

+0

Fwiw, MySQL 5.5 integrado con soporte SSL incluye un 'SHA2 () 'función que proporciona SHA224, SHA256, SHA384 y algoritmos de hash SHA512. Si está utilizando una versión anterior de MySQL, use la función 'hash()' en PHP. –

+0

¡Gracias de nuevo, Bill, esta es la segunda vez que ayudas! Estoy usando 5.1 porque vino con WAMP (wampserver.com). Tuve que desinstalar mi viejo MySQL para instalar este. Desafortunadamente, no estoy seguro de cómo actualizarlo ... Intentaré usar PHP para mi cifrado. – Tarik

Respuesta

5

En primer lugar, su DBMS (MySQL) no necesita tener ningún apoyo a los hashes criptográficos. Puedes hacer todo eso en PHP, y eso es lo que deberías hacer.

Si desea almacenar sal y hash en la misma columna, debe concatenarlos.

// the plaintext password 
$password = (string) $_GET['password']; 

// you'll want better RNG in reality 
// make sure number is 4 chars long 
$salt = str_pad((string) rand(1, 1000), 4, '0', STR_PAD_LEFT); 

// you may want to use more measures here too 
// concatenate hash with salt 
$user_password = sha512($password . $salt) . $salt; 

Ahora, si desea verificar una contraseña que haces:

// the plaintext password 
$password = (string) $_GET['password']; 

// the hash from the db 
$user_password = $row['user_password']; 

// extract the salt 
// just cut off the last 4 chars 
$salt = substr($user_password, -4); 
$hash = substr($user_password, 0, -4); 

// verify 
if (sha512($password . $salt) == $hash) { 
    echo 'match'; 
} 

Es posible que desee echar un vistazo a phpass, que también utiliza esta técnica. Es una solución de hash de PHP que utiliza la salazón entre otras cosas.

Definitivamente, debe echarle un vistazo a la respuesta a la pregunta a la que se vinculó WolfOdrade.

+0

Gracias! Muchas funciones nuevas, pero puedo descifrar la esencia de mí mismo. Esto es exactamente lo que estaba buscando. Nunca supe sobre la función de cadena de resta, eso ayuda. ¿Es posible restar del frente de una cuerda una ubicación de sal diferente? ¡Gracias de nuevo! – Tarik

+0

Claro, substr puede manejar ambos. Si tienes una sal de 4 caracteres en la parte delantera, harías: '$ salt = substr ($ user_password, 0, 4); $ hash = substr ($ user_password, 4); ' – igorw

+0

Gracias. Intenté el hash_hmac, pero tengo problemas para comparar la contraseña de inicio de sesión con la contraseña de la base de datos. La sal en el hash_hmac se genera aleatoriamente, entonces ¿cómo puedo restarla? También noté lo mismo en tu ejemplo. sha512 ($ password. $ salt) está hash la contraseña y una sal única. ¿Cómo podría obtener esa sal única para actualizar la contraseña ingresada con el pase de la base de datos? Perdón por la sobrecarga de la pregunta, ¡estoy a solo unos centímetros de esto! – Tarik

3

Esto parece cubierto en profundidad en un post anterior: Secure hash and salt for PHP passwords

+0

Leí la mejor respuesta para esto antes de hacer esta pregunta y no respondió mi pregunta. Proporciona una buena manera de almacenar una contraseña de forma segura, pero no es exactamente lo que estoy buscando. – Tarik

0

Personalmente recomiendo permitir que MySQL haga esto con sus funciones integradas.

La forma en que lo hago es crear una función en el archivo de configuración de mi base de datos que devuelve una cadena de clave. El archivo de configuración debe estar fuera de la raíz de su sitio para que el servidor web pueda acceder al archivo pero no a otros. así por ejemplo:

function enc_key(){ 
    return "aXfDs0DgssATa023GSEpxV"; 
} 

Luego, en la secuencia de comandos puede utilizar con la consulta SQL y funciones AES_ENCRYPT y AES_DECRYPT en MySQL como esto:

require_once('dbconf.inc.php'); 

$key = enc_key(); 

//When creating a new user 
$sql = "INSERT INTO users (username, password) VALUES ('bob', AES_ENCRYPT('{$key}', {$password}))"; 

//When retrieving users password 
$sql = "SELECT AES_DECRYPT('{$key}', password) AS password FROM users WHERE username like 'bob'"; 
+0

Esto realmente no es una buena idea. No debe cifrar las contraseñas, debe hash (si alguien piratea su servidor, tendría acceso completo a las contraseñas de todos los usuarios). También está implicando la inyección SQL a través de la ausencia de escape. – igorw

+0

En primer lugar, me doy cuenta de que las cadenas allí están abiertas a la inyección sql; sin embargo, este no fue el tema de la discusión. Las sentencias sql son solo ejemplos y supongo que se dan cuenta de la necesidad de desinfectar su entrada de usuario. No estoy aquí para escribir la solicitud. Estoy aquí para responder preguntas específicas. –

+0

En segundo lugar, el cifrado bidireccional es tan seguro como el "hash" siempre que mantenga la clave a salvo. Me doy cuenta de que si alguien piratea tu servidor tienen sus contraseñas PERO si alguien piratea tu servidor, tienen acceso a todo, incluso a cualquier otra información en la base de datos, así que las contraseñas hash se convierten en un punto discutible ¿no crees? –