views:

59

answers:

1

I have a rails model with a hashed password field in it (surprise, surprise), which after some manipulation, is 40 characters long. I generate a user in script/console and it appears as follows:

#<User id: 1, firstname: "true", lastname: "false", username: "chaines51", hashed_password: "2Gr0GWvPunB3x5jomRTSTZJRIelC2RW103d7f3db">

I then run user_instance.save, which returns true, and the user then looks like this:

#<User id: 1, firstname: "true", lastname: "false", username: "chaines51", hashed_password: "103d7f3db">

Any idea what is happening to the other 30+ characters? I changed the field in the migration from string to text, but it still gets truncated

EDIT: The model code is:

require 'digest/sha1'

class User < ActiveRecord::Base
  validates_presence_of :username, :password, :password_confirmation, :firstname, :lastname
  validates_length_of :username, :within => 3..40
  validates_length_of :password, :within => 5..40
  validates_uniqueness_of :username
  validates_confirmation_of :password
  belongs_to :school

  attr_protected :id, :salt
  attr_accessor :password, :password_confirmation

  def self.random_string(len)
    #generate a random salt consisting of digits and letters.
    chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
    salt = ""
    1.upto(len) { |i| salt << chars[rand(chars.size-1)] }
    return salt
  end

  def password=(pass)
    @password=pass
    @salt = User.random_string(40-pass.length)
    self.hashed_password = User.encrypt(@password, @salt)
  end  

  def self.encrypt(pass, salt)
    hash = Digest::SHA1.hexdigest(pass+salt)
    hash.slice!(0..(40-pass.length-1))
    hash = salt+hash;
  end

  def self.checkhash(pass, hash)
    salt = hash.slice!(0..40-pass.length-1)
    rehash = User.encrypt(pass, salt)
    return rehash == (salt+hash)
  end

  def self.authenticate(login, pass)
    u = User.find_by_username(login)
    return nil if u.nil?
    return u if User.checkhash(pass, u.hashed_password)
    nil
  end
end

and the db/schema.rb is:

ActiveRecord::Schema.define(:version => 20100127034504) do

  create_table "categories", :force => true do |t|
    t.string "title"
  end

  create_table "questions", :force => true do |t|
    t.string   "question"
    t.string   "a"
    t.string   "b"
    t.string   "c"
    t.string   "d"
    t.string   "e"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "questions_quizzes", :id => false, :force => true do |t|
    t.integer  "app_id"
    t.integer  "category_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "quizzes", :force => true do |t|
    t.string  "title"
    t.integer "category_id"
  end

  create_table "schools", :force => true do |t|
    t.string  "name"
    t.integer "coach_id"
  end

  create_table "users", :force => true do |t|
    t.string   "firstname",                          :null => false
    t.string   "lastname",                           :null => false
    t.string   "username",                           :null => false
    t.boolean  "needs_pass",      :default => false
    t.integer  "school_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.boolean  "confirmed",       :default => false
    t.text     "hashed_password"
  end

end
+1  A: 

Showing the model code, and the table info form db/schema.rb, would be really helpful. Right off, I can tell you that a string column will hold up to 255 characters without a problem, so there might be something else at fault. If something is restricting, it will most likely show itself in one of the two places I named above.

Jaime Bellmyer
done and done. I don't see anything out of the ordinary (besides a pretty terribly written model), but I wouldn't be posting here if I did :P
Cody Haines
I just noticed something interesting - in your original code snippets above, both versions have an id. That means both versions had already been saved once, right? Can you go to script/console and walk through the creation of a new user? Sorry for all the extra work, but this is the fun world of debugging :)
Jaime Bellmyer
so what gets saved in the DB, exactly? Also does it only get truncated when the save occurs?
rogerdpack
hash.slice!(0..(40-pass.length-1))shouldn't that be hash.slice!(0..(40-salt.length-1))?
rogerdpack
*sigh*. I found the problem. It was completely unrelated to the save method, but rather the rehash method when called by the authenticate method... slice! and slice are two different functions with very different results :P
Cody Haines
and, the DB saved properly, but I never went and accessed it manually, assuming my authenticate method was correct (bad idea...)And, no, hash.slice(0..(40-pass.length-1)) was correct, because I based the salt length at pass.length, so I could (should) change it to simply 0..salt.length-1
Cody Haines
@Cody: could you summarize and add an answer with your solution?
zetetic