2014-01-13 41 views
2

這是從GitHub的頁面:bcrypt與salt發生了什麼?

require 'bcrypt' 

class User < ActiveRecord::Base 
    # users.password_hash in the database is a :string 
    include BCrypt 

    def password 
    @password ||= Password.new(password_hash) 
    end 

    def password=(new_password) 
    @password = Password.create(new_password) 
    self.password_hash = @password 
    end 
end 

看來,訪問密碼的方法,你需要調用它作爲從屬性創建方法:

@user.password = user_params[:password] 
@user.save 

好吧.. 。精細?但現在儲存的鹽在哪裏?我根本不明白,這又如何遠程安全呢?

要檢索散列密碼,則需要此方法:

def password 
    @password ||= Password.new(password_hash) 
    end 

,並調用它作爲一個屬性:

if @user.password == params[:password] 
    give_token 
    else 
    false 
    end 

所以它似乎一切都沒有工作鹽......是怎麼做的做這個?

這意味着我現在只需要在我的數據庫中使用一列來處理passowords,對吧? passwordpassword_hash而不是password_salt | password_hash

好那麼爲什麼GitHub的頁面這樣說:

但是,即使這有弱點 - 攻擊者可以通過只相同的算法運行的 可能的密碼列表,結果存儲在一個 大數據庫,然後通過哈希查找密碼:

PrecomputedPassword.find_by_hash(<unique gibberish>).password #=> "secret1" 
Salts 

然後這真的打動了我:

The solution to this is to add a small chunk of random data -- called a salt -- to the password before it's hashed: 

爲什麼他們解釋這一切如果bcrypt自動處理一切嗎?

hash(salt + p) #=> <really unique gibberish> 
The salt is then stored along with the hash in the database, and used to check potentially valid passwords: 

<really unique gibberish> =? hash(salt + just_entered_password) 
bcrypt-ruby automatically handles the storage and generation of these salts for you. 

有人能解釋如何存儲bcrypt和產生這些鹽?爲什麼它說它爲我處理這一切,然後繼續告訴我如何產生鹽?我是否需要在我的模型中運行如下所示的內容:self.password_hash = hash(salt + p)

呃很混亂我以前完全得到鹽和哈希值,現在他們已經改變了這一切。 可怕的,不清楚的文檔 ...他們似乎向你展示瞭如何在沒有鹽的情況下使用bcrypt並加載示例,然後簡要提及如何使用底部的鹽正確地做到這一點。

有人請給我一個例子如何使用新版本的bcrypt來生成鹽和哈希,以及如何進行身份驗證?

+0

無論你摸不着頭腦,你應該停止你正在做什麼,並使用'has_secure_password',它爲您管理存儲密碼安全的*極不平凡的*任務。 – meagar

+0

Godammit我很好,用bcrypt自己抨擊自己。爲什麼他們必須改變這一切? – Starkers

+0

我以爲'has_secure_password'使用bcrypt,但我可能是錯的 – meagar

回答

11

好的,has_secure_password真的很酷。您不必擔心鹽和散列,鹽和散列在數據庫中作爲一個屬性(password_digest)存儲。

它以這樣的方式保存,bcrypt知道password_digest字符串的哪一部分是salt,什麼是散列。

如果你從頭開始設置身份驗證,你從字面上需要做到以下幾點:

1)添加bcrypt軌寶石:

gem bcrypt-rails 

2)添加has_secure_password方法模型

class User < ActiveRecord::Base 
    has_secure_password 
end 

3)確保用戶表中有一個password_digest列:

012處理您的用戶記錄任務
class CreateUser < ActiveRecord::Migration 
    create_table :users do |t| 
     t.username 
     t.password_digest 
    end 
end 

4)創建一個new方法創建AA新的空用戶實例的形式使用:

class UsersController < ApplicationController 
    def new 
     @user = User.new 
    end 
end 

5)在new視圖,使創建的表單填充params哈希表」 :password:username條目:

<% form_for(@user) do |f| %> 
    <%= f.text_field :username %> 
    <%= f.password_field :password %> 
<% end %> 

6)早在我們的控制器,允許用戶名和使用強PARAMS密碼。背後強大的PARAMS的全部原因是爲了防止一些厚臉皮的傢伙利用開發工具創建自己的HTML表單字段(如一個關於ID)和惡意數據填充數據庫:

class UsersController < ApplicationController 
    def new 
     @user = User.new 
    end 

    private 

    def user_params 
      params.require(:user).permit(:username, :password) 
    end 
end 

7)讓我們創建在創建將使用這些允許的輸入來創建一個新的用戶,通過表格填充方法:

class UsersController < ApplicationController 
    def new 
     @user = User.new 
    end 

    def create 
      @user = User.new(user_params) 
      @user.save 
      redirect_to root_path 
    end 

    private 

    def user_params 
      params.require(:user).permit(:username, :password) 
    end 
end 

設置你的路由你認爲合適的,這就是它!用戶記錄的password_digest列將自動填充一個字符串,其中包含一個鹽,並附帶密碼的散列。十分優雅。

您只需要記住:passwordpassword_digest

爲了對用戶進行授權和signout用戶,以創建方法創建一個會話控制器和破壞方法:

def create 
    user = User.find_by_email(params[:email]) 
    if user && user.authenticate(params[:password]) 
    session[:user_id] = user.id 
    redirect_to admin_root_path, :notice => "Welcome back, #{user.username}" 
    else 
    flash.now.alert = "Invalid email or password" 
    redirect_to root_path 
    end 
end 

def destroy 
    reset_session 
    flash[:info] = "Signed out successfully!" 
    redirect_to root_path 
end 

希望這可以幫助別人!

1

bcrypt爲你覆蓋了一切。您的密碼摘要包含幾種類型的信息,bcrypt算法類型,成本,鹽分和校驗和。

例如:

my_password = BCrypt::Password.create("my password") 
#=> "$2a$10$.kyRS8M3OICtvjBpdDd1seUtlvPKO5CmYz1VM49JL7cJWZDaoYWT." 

第一部分:$2a$是算法見的變體:Where 2x prefix are used in BCrypt?

第二部分10是成本參數,可以增加它拖慢進程(對數值),通過提供散列{cost: 12}作爲create的第二個參數。

現在,如果您致電my_password.salt,您會得到"$2a$10$.kyRS8M3OICtvjBpdDd1se",它標識正在用作創建校驗和關鍵的那部分。

最後,你的校驗"UtlvPKO5CmYz1VM49JL7cJWZDaoYWT."。這是因爲如果您第二次撥打create字符串將會因爲另一個鹽將被使用而不同,那麼這是原因。

但正如我前面提到的,你不需要做任何額外的東西,因爲所有這些都被照顧你。