views:

438

answers:

2

I have this algorithm in Java to store passwords in database. I'd like to re-write my application in Ruby on Rails, so I need the same algorithm to compare hashed passwords. What's the Ruby equivalent of this algorithm?

public static String encrypt(String password) {
 MessageDigest md;
 try {
  md = MessageDigest.getInstance("SHA");
  md.update(password.getBytes("UTF-8")); // step 3
  byte raw[] = md.digest(); // step 4
  String hash = (new BASE64Encoder()).encode(raw); // step 5
  return hash; // step 6
 } catch (NoSuchAlgorithmException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } catch (UnsupportedEncodingException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } 
 return null;
}

Just for testing purpose, the "teste123" password generates this hash in my Java version: PQ87ndys7DDEAIxeAw5sE6R4y08=

+1  A: 

Before you go any further, stop what you're doing and read this Coding Horror article: You're Probably Storing Passwords Incorrectly.

Using a plain hash, with no salt, to encode passwords is nearly as bad as not using any hashing at all.

Greg Hewgill
You are right! It was a mistake of 4 years ago. But I can't restore the already stored passwords from the database, can I? I will add a salt, but I still need to know how to do it in Ruby.
Daniel Cukier
Fair enough, I was afraid it might be a legacy system issue. In general, you can't directly restore the already-stored passwords, except perhaps by using a rainbow table attack (a lot of work for little benefit really). One approach might be to present your users with: "Hi! Your password has expired. Please update your password before proceeding." and store the current password encoding mechanism in your database (so you know who has updated and who hasn't).
Greg Hewgill
Another option would be re-hash the already hashed password with a salt, something like this: new_hash(old_hash(password), salt) - and store all password like this
Daniel Cukier
Right, good idea. I just came back to this question to add that note, and found you beat me to it!
Greg Hewgill
+2  A: 

Before you read this, read Greg's answer about hashing.

Then:

import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test {
  public static String encrypt(String password) {
    MessageDigest md;
    try {
      md = MessageDigest.getInstance("SHA");
      md.update(password.getBytes("UTF-8")); // step 3
      byte raw[] = md.digest(); // step 4
      String hash = (new BASE64Encoder()).encode(raw); // step 5
      return hash; // step 6
    } catch (NoSuchAlgorithmException e) {
    } catch (java.io.UnsupportedEncodingException e) {
    }
    return null;
  }

  public static void main(String[] args) {
    System.out.println(encrypt("my password"));
  }
}

This outputs

ovj3+hlaCAoipokEHaqPIET58zY=

In Ruby:

require 'digest/sha1'
require 'base64'
Base64.b64encode Digest::SHA1.digest('my password')

also outputs

ovj3+hlaCAoipokEHaqPIET58zY=

Jim Puls
I get a "\n" with Base64.b64encode Digest::SHA1.digest('my password'):=> "ovj3+hlaCAoipokEHaqPIET58zY=\n"
Daniel Cukier
Is this seriously a problem? It's not like \n is a valid Base64 character; you can strip it out, yes?
Jim Puls
require 'digest/sha1'require 'base64'Base64.b64encode(Digest::SHA1.digest('my password')).chomp
Anko