2009-02-09 30 views
8

Tôi có một cơ sở dữ liệu lớn của người dùng (~ 200.000) mà tôi đang chuyển từ một ứng dụng ASP.NET sang ứng dụng Ruby on Rails. Tôi không thực sự muốn yêu cầu mọi người dùng đặt lại mật khẩu của họ và vì vậy tôi đang cố gắng triển khai lại hàm băm mật khẩu C# trong Ruby.Thực hiện lại ASP.NET Membership và Mật khẩu người dùng Hashing trong Ruby

Chức năng cũ là thế này:

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); 
} 

Một ví dụ băm mật khẩu và muối là (và mật khẩu được sử dụng là "password"):

băm mật khẩu: "weEWx4rhyPtd3kec7usysxf7kpk =" Salt: " 1ptFxHq7ALe7yXIQDdzQ9Q ==" Mật khẩu: "password"

Bây giờ với các mã Ruby sau:

require "base64" 
require "digest/sha1" 


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

concat = salt+password 

sha1 = Digest::SHA1.digest(concat) 

encoded = Base64.encode64(sha1) 

puts encoded 

Tôi không nhận được mật khẩu băm đúng (Tôi nhận được "+ BsdIOBN/Vh2U7qWG4e + O13h3iQ =" thay vì "weEWx4rhyPtd3kec7usysxf7kpk ="). Có ai có thể thấy vấn đề có thể là gì không?

Rất cám ơn

Arfon

Trả lời

8

Chỉ cần một cập nhật nhanh chóng, một đồng nghiệp của tôi đã giải quyết này:

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

Bạn cần phải unencode muối để chuyển đổi nó trở lại đại diện byte của nó và sau đó tiếp nhau rằng với mật khẩu để có được giá trị mật khẩu băm. Bạn đang sử dụng chuỗi mã hóa muối trực tiếp (một muối khác) và do đó nó đang băm nhỏ đến một thứ khác.

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

Bạn đang bỏ qua một bước quan trọng: chuyển đổi mật khẩu vào byte. –

+0

OK, có vẻ như tôi sẽ phải giảm xuống mức byte để thực hiện việc này? – arfon

+0

@Adam - không chắc chắn. Trong .NET nó đặt chúng vào một mảng byte để chuyển sang thuật toán băm. Ruby thực sự có thể làm điều tương tự bằng cách sử dụng một chuỗi đơn giản. Nếu chúng được lưu trữ dưới dạng null, nó cơ bản giống như bộ đệm trong ví dụ .NET. Tôi sẽ cho nó xoáy và xem nó có hiệu quả không. – tvanfosson

2

Bạn đang ở khá gần. Thật không may Ruby không có hỗ trợ unicode tích hợp vào lúc này, và hàm băm của bạn dựa vào nó. Có cách giải quyết. Nhìn xung quanh trang web về cách làm unicode trong Ruby. BTW, tôi nghĩ rằng bạn quên base64 giải mã muối, có vẻ như chức năng ASP.net làm điều đó.

3

Tôi đã được giao nhiệm vụ di chuyển một ứng dụng .NET hiện có để Ruby on Rails. Tôi đang sử dụng mã dưới đây để bắt chước băm mật khẩu .NET. Tôi rất mới với Ruby, và không biết .NET chút nào. Mã có thể không sạch như nó có thể, nhưng đó là một sự khởi đầu.

Để kiểm tra, lưu này như một kịch bản Ruby và chạy với:

ruby ​​script plain_text_password salt_in_base64

ví dụ

ruby ​​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

Wow người đàn ông, tôi đã chơi với điều này mãi mãi và mã của bạn đã làm nó. Tôi nghĩ rằng bạn đang cố gắng để tái tạo mã rất giống nhau. Tôi đã thử rất nhiều thứ khác nhau và rất gần với bạn, nhưng nó hơi khác một chút. Tôi đã được đóng gói và giải nén với "S *". Cảm ơn rất nhiều. – Amala

Các vấn đề liên quan