Overriding ASP.NET Membership and User Password in Ruby

I have a large user database (~ 200,000) that I am moving from an ASP.NET application to a Ruby on Rails application. I really do not want to ask each user to reset their password, and therefore I am trying to re-implement the C # password hashing function in Ruby.

The old function is this:

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

An example of a hashed password and salt (and the password was "password"):

Hashed password: "weEWx4rhyPtd3kec7usysxf7kpk =" Salt: "1ptFxHq7ALe7yXIQDdzQ9Q ==" Password: "password"

Now with the following Ruby code:

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

I do not get the correct password hash (I get "+ BsdIOBN / Vh2U7qWG4e + O13h3iQ =" instead of "weEWx4rhyPtd3kec7usysxf7kpk ="). Can anyone understand what could be the problem?

Thank you very much

Arfon

+8
ruby ruby-on-rails base64 sha1
Feb 09 '09 at 22:52
source share
4 answers

Just a quick update, my colleague decided this:

 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 
+8
Feb 11 '09 at 11:56
source share

I was tasked with migrating my existing .NET application to Ruby on Rails. I use the code below to simulate the hashing of .NET passwords. I am very new to Ruby and don't know .NET at all. The code may not be as clean as possible, but this is the beginning.

To test, save this as a Ruby script and run with:

ruby script plain_text_password salt_in_base64

eg.

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 
+3
Nov 18 2018-11-11T11
source share

You are pretty close. Unfortunately, Ruby does not have native Unicode support at the moment, and your hash function relies on it. There are workarounds. Check out the site on how to make unicode in Ruby. By the way, I think you forgot base64 to decrypt the salt, it looks like the ASP.net function does this.

+2
Feb 09 '09 at 23:11
source share

You need an unencode salt to convert it back to this byte representation, and then combine this with a password to get the hashed password value. You are using a direct encoding string (which is a different salt) and thus it is hashed by something else.

 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 
+1
Feb 09 '09 at 23:01
source share



All Articles