2009-02-09 13 views
8

Tengo una gran base de datos de usuarios (~ 200,000) que estoy transfiriendo desde una aplicación ASP.NET a una aplicación Ruby on Rails. Realmente no quiero pedirle a cada usuario que restablezca su contraseña, así que estoy tratando de volver a implementar la función de hashing de contraseñas de C# en Ruby.Reimplement Membresía ASP.NET y hashing de contraseña de usuario en Ruby

La función de edad es la siguiente:

public string EncodePassword(string pass, string saltBase64) 
{ 
    byte[] bytes = Encoding.Unicode.GetBytes(pass); 
    byte[] src = Convert.FromBase64String(saltBase64); 
    byte[] dst = new byte[src.Length + bytes.Length]; 
    Buffer.BlockCopy(src, 0, dst, 0, src.Length); 
    Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length); 
    HashAlgorithm algorithm = HashAlgorithm.Create("SHA1"); 
    byte[] inArray = algorithm.ComputeHash(dst); 
    return Convert.ToBase64String(inArray); 
} 

Un ejemplo hash contraseña y la sal es (y la contraseña utilizada fue "contraseña"):

contraseña hash: "weEWx4rhyPtd3kec7usysxf7kpk =" sal: " 1ptFxHq7ALe7yXIQDdzQ9Q ==" contraseña: "contraseña"

Ahora, con el siguiente código de Ruby:

require "base64" 
require "digest/sha1" 


password = "password" 
salt = "1ptFxHq7ALe7yXIQDdzQ9Q==" 

concat = salt+password 

sha1 = Digest::SHA1.digest(concat) 

encoded = Base64.encode64(sha1) 

puts encoded 

No obtengo el hash de contraseña correcto (obtengo "+ BsdIOBN/Vh2U7qWG4e + O13h3iQ =" en lugar de "weEWx4rhyPtd3kec7usysxf7kpk ="). ¿Alguien puede ver cuál podría ser el problema?

Muchas gracias

Arfon

Respuesta

8

Sólo una rápida actualización, un colega mío ha resuelto este:

require "base64" 
require "digest" 
require "jcode" 


def encode_password(password, salt) 
bytes = "" 
password.each_char { |c| bytes += c + "\x00" } 
salty = Base64.decode64(salt) 
concat = salty+bytes 
sha1 = Digest::SHA1.digest(concat) 
encoded = Base64.encode64(sha1).strip() 
puts encoded 
end 
1

Se necesitan descodifica la sal para convertirlo de nuevo a su representación de bytes y luego concatenar que con la contraseña para obtener el valor hash de la contraseña. Estás utilizando la cadena de sal de codificación directamente (que es una sal diferente) y, por lo tanto, se trata de algo diferente.

require "base64" 
require "digest/sha1" 
password = "password" 
salt = Base64.decode64("1ptFxHq7ALe7yXIQDdzQ9Q==") 
concat = salt+password 
sha1 = Digest::SHA1.digest(concat) 
encoded = Base64.encode64(sha1) 
puts encoded 
+0

Estás saltarse un paso importante: la conversión de contraseña en bytes. –

+0

OK, ¿así que parece que tendré que bajar al nivel de bytes para hacer esto entonces? – arfon

+0

@ Adam - no estoy seguro. En .NET, los está poniendo en una matriz de bytes para transferirlos al algoritmo hash. Ruby puede hacer lo mismo con una cuerda simple. Si se almacenan como terminadas en nulo, es esencialmente lo mismo que el búfer en el ejemplo de .NET. Me gustaría darle vueltas y ver si funciona. – tvanfosson

2

Estás muy cerca. Desafortunadamente, Ruby no tiene soporte para Unicode incorporado en este momento, y tu función de hashing depende de ello. Hay soluciones. Mire alrededor del sitio sobre cómo hacer unicode en Ruby. Por cierto, creo que olvidó decodificar la sal base64, parece que la función ASP.net hace eso.

3

Me han encargado con la migración de una aplicación .NET existente para Ruby on Rails. Estoy usando el código a continuación para imitar el hashing de la contraseña .NET. Soy muy nuevo para Ruby, y no conozco .NET en absoluto. Es posible que el código no sea tan limpio como podría, pero es un comienzo.

Para probar, salva esto como un script de Ruby y correr con:

rubí script de plain_text_password salt_in_base64

por ejemplo,

rubí dotNetHash.rb password123 LU7hUk4MXAvlq6DksvP9SQ ==

require "base64" 
require "digest" 

# Encode password as double-width characters 
password_as_text = ARGV.first 
double_width_password = [] 
double_width_password = password_as_text.encode("UTF-16LE").bytes.to_a 

# Unencode the salt 
salt = Base64.decode64(ARGV[1]) 

# Concatenate salt+pass 
salt_pass_array = [] 
salt_pass_array = salt.bytes.to_a + double_width_password 

# Repack array as string and hash it. Then encode. 
salt_pass_str = salt_pass_array.pack('C*') 
sha1_saltpass = Digest::SHA1.digest(salt_pass_str) 
enc_sha1_saltpass = Base64.encode64(sha1_saltpass).strip() 
puts "Encoded SHA1 saltpass is " + enc_sha1_saltpass 
+0

Guau, yo estaba jugando con esto para siempre y tu código lo hizo. Creo que estás tratando de replicar un código muy similar. Estaba probando muchas cosas diferentes y estaba muy cerca de la tuya, pero fue un poco diferente. Estaba empacando y desempacando con "S *". Muchas gracias. – Amala

Cuestiones relacionadas