2

我想通过使用 PBKDF2 并将密码哈希和盐存储在数据库中来实现用户身份验证。

我的用户类看起来像这样

class User < Couchbase::Model
  require 'pbkdf2'

  attribute :name
  attribute :surname
  attribute :email
  attribute :type
  attribute :password
  attribute :password_hash
  attribute :password_salt

  attribute :user_since, :default => lambda{ Time.now }

  #... Some not so interesting validates

  before_create :prepare_to_create

  #returns the document of the user found for the given id
  def self.retrieve(id)
    return User.bucket.get(id)
  end

  def encrypt_password
    if self.password.present? then
      hashedpassword = create_password(self.password)
    self.password_hash = hashedpassword.value
    self.password_salt = hashedpassword.salt
    end
  end

  #Creates a new PBKDF2 instance with the given string
  #and the given salt. If no salt is specified
  # a SecureRandom.base(16) string is used
  def create_password(pwString, saltString = SecureRandom.urlsafe_base64(16))
    password = PBKDF2.new do |p|
      p.password = pwString
      p.salt = saltString
      p.iterations = 5000
    end
  end

  def prepare_to_create
    encrypt_password
    @id = User.bucket.incr("user_key", 1, :initial => 1).to_s
  end

end

控制器看起来像这样:

class UsersController < ApplicationController
  def new
    @user = User.new
    @user.type = params[:type]
  end

  def create
    @user = User.new(params[:user])    
    if @user.save
      data = User.retrieve(@user.id)
      newUser = User.new(:name => data[:name],
                         :surname => data[:surname],
                         :email => data[:email],
                         :type => data[:type],
                         :password => data[:password])

      redirect_to root_url, :notice => "You successfully signed up " + newUser.full_name 
    else
      render "new"
    end
  end

end

它的安全性很好,但是当我调用检索以查找用户时,我得到一个异常,看起来密码哈希包含非 UTF-8 字符。

它看起来像这样:

Couchbase::Error::ValueFormat (unable to convert value for key '8': lexical error: invalid bytes in UTF8 string.
      :"123456","password_hash":"\r�����;��X�\u001E���S=c\u0018���
                 (right here) ------^
):

现在我想知道我是否必须以某种方式清理密码。我必须转义一些字符吗?还是我应该使用其他加密功能?

PS:我知道密码以清除类型存储,我稍后会修复它:)

4

1 回答 1

2

好吧,如果你只是打电话hashedpassword.value,你会得到哈希的二进制表示,你必须像下面这样调用它:

def encrypt_password
    if self.password.present? then
      hashedpassword = create_password(self.password)
      self.password_hash = hashedpassword.hex_string
      self.password_salt = hashedpassword.salt
  end
end
于 2013-02-18T14:17:56.330 回答