在Ruby中重新实现ASP.NET成员资格和用户密码哈希

我有一个庞大的用户数据库(~200,000),我正在从ASP.NET应用程序转移到Ruby on Rails应用程序。 我真的不想让每个用户重置他们的密码,所以我试图在Ruby中重新实现C#密码散列函数。

旧function是这样的:

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

示例哈希密码和salt是(并且使用的密码是“password”):

哈希密码:“weEWx4rhyPtd3kec7usysxf7kpk =”盐:“1ptFxHq7ALe7yXIQDdzQ9Q ==”密码:“密码”

现在使用以下Ruby代码:

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

我没有得到正确的密码哈希(我得到“+ BsdIOBN / Vh2U7qWG4e + O13h3iQ =”而不是“weEWx4rhyPtd3kec7usysxf7kpk =”)。 任何人都可以看到问题可能是什么?

非常感谢

Arfon

只是一个快速更新,我的一位同事解决了这个问题:

 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 

我的任务是将现有的.NET应用程序迁移到Ruby on Rails。 我使用下面的代码来模仿.NET密码散列。 我是Ruby的新手,根本不懂.NET。 代码可能不尽如人意,但它是一个开始。

要进行测试,请将其另存为Ruby脚本并运行:

ruby script plain_text_password salt_in_base64

例如

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 

你很近。 不幸的是,Ruby目前没有内置的unicode支持,你的散列函数依赖于它。 有解决方法。 查看网站上有关如何在Ruby中执行unicode的信息。 顺便说一句,我想你忘了base64解码盐,看起来像ASP.net函数那样做。

您需要对salt进行解码以将其转换回其字节表示forms,然后将其与密码连接以获取散列密码值。 你直接使用编码盐字符串(这是一个不同的盐),因此它是散列不同的东西。

 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