2011-01-08 107 views
6

幾年來我在這裏問了關於如何使PHP密碼存儲安全的stackoverflow。 的main answer建議使用以下哈希算法:PHP密碼存儲與HMAC +隨機數 - 隨機性隨機性重要嗎?

function hash_password($password, $nonce) { 
    global $site_key; 
    return hash_hmac('sha512', $password . $nonce, $site_key); 
} 

答案建議使用一個隨機現時。隨機隨機數比簡單唯一隨機數有什麼優勢?

例如,每個用戶可以具有其自己的ID,該ID不會改變。但是,我們假設用戶ID是順序的(使用MySQL的自動增量功能構建),因此不是隨機的。用戶ID是一個很好的隨機數還是隨機性很重要?

現在,每個用戶都可以選擇一個用戶名。每個用戶都有自己的用戶名,不會更改,並且兩個不同的用戶不能具有相同的用戶名。 用戶名仍然不是隨機的,但它們也不是順序的。用戶名是否足夠好作爲隨機數?它會比使用用戶ID好嗎?

+0

你現時應該是鹽。根據定義,鹽是隨機的。我已經寫在這裏醃製長回答:http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190 – Jacco 2011-01-09 17:26:56

回答

2

這是所有對隨機數是鹽ASSUMPTION ...

如果現時你的意思是鹽,然後是需要被更加彩虹表。通常情況下,一旦超過20個字符的鹽就足夠了,但對於極端的安全條件,您需要爲每個密碼添加一個新的隨機鹽。

緩慢散列http://www.php.net/manual/en/function.hash.php#89574也是不錯的選擇,沒有諷刺。但我喜歡成熟。

Did not see the bottom half of your response。詳細說明:Nonces用於防止使用彩虹表。 ID是否會起作用僅取決於ID的長度。隨機性在技術上並不重要,但只是需要更多的彩虹表。例如,假設您使用字符「a」作爲隨機數,並且密碼長度爲2個字符,則必須創建a-aa,a-ab a-ac等彩虹表。如果每次使用一個隨機字符,可能需要完成'a'的所有排列+其他隨機字符的所有permuatations。

但是一般來說製作彩虹桌需要相當長的時間。所以,如果你想出一個鹽,它可能是彩虹表,因爲它不存在。

+0

這個答案是正確的,但沒有任何與題。 HMAC不是一個哈希,而是一個MAC算法。也稱爲鍵控哈希。因此,現時問題不是正確的術語。它應該是(私人)鑰匙。在這種情況下,一個關鍵是安全的(除非你工作或想防範國家機構)。 – Henri 2011-01-08 19:16:18

+0

因此,名稱「NoviceCoding」...非常感謝解釋。我試圖分享我對這些事情的小知識,但像這次一樣,它是無關緊要的。再次感謝。 – NoviceCoding 2011-01-08 19:28:19

0

對於存儲的密碼足夠使用:

sha512(salt + password) 

salt應該隨機併爲每個用戶唯一。隨機鹽會使預先計算的散列表攻擊變得不可能:每個用戶將需要他自己計算的散列表。如果您不使用隨機鹽,那麼預先計算的表格存在的可能性會更高。

定位鹽密碼前將有助於隱藏哈希模式,以防某些用戶具有相同的密碼。

隨機數不需要,因爲它用於預防回覆攻擊。這種保護在您的架構中是不可能的。

使用HMAC防止碰撞是無用的,因爲:a)我們使用散列不用於MAC,B),以使衝突的概率爲50%SHA-512 you need to calculate大約2^256個值。而2^256是真正的天文數字。

2

我發現有網上寫關於這個話題相當不錯的教程。我不太記得在谷歌,我發現它,但讓我看看,如果我能打破功能下降不夠好自己,因爲它是正確的在我的面前......

首先的功能,它可以創建一個鍵任何大小的長度。我把它發表評論相當大量的自由......

function pbkdf2($password,$salt,$iter_count = 1500,$key_length = 32,$algorithm = 'sha512') 
{ 
    /* 
     @param string password -- password to be encrypted 
     @param string salt -- salt to encrypt with 
     @param int iter_count -- number of times to iterate blocks 
     @param key_length -- length of key to return 
     @param $algorithm -- algorithm to use in hashing 

     @return string key 
    */ 

    //determine the length of the hahs 
    $hash_length = strlen(hash($algorithm,NULL,TRUE)); 
    //determine the number of key blocks to compute 
    $key_blocks = ceil($key_length/$hash_length); 
    //initialize key 
    $key = ''; 

    //create the key itself 
    //create blocks 
    for($block_count = 1;$block_count <= $key_blocks;$block_count++) 
    { 
     //initalize hash for this block 
     $iterated_block = $block = hash_hmac($algorithm,$salt.pack('N',$block_count),$password,TRUE); 
     //iterate blocks 
     for($iterate = 1;$iterate <= $iter_count;$iterate++) 
     { 
      //xor each iterate 
      $iterated_block ^= ($block = hash_hmac($algorithm,$block,$password,TRUE)); 
     } 
     //append iterated block 
     $key .= $iterated_block; 
    } 
    //return the key 
    return substr($key,0,$key_length); 
} 
  1. 第一件事情就是找出散列的長度。
  2. 接着它確定密鑰塊多少所需的密鑰長度指定
  3. 然後,它初始化散列(鍵)以返回
  4. 設置for循環將創建每個塊
  5. 取初始散列與附加到鹽
  6. 二進制塊計數器塊的開始循環迭代的塊$ iter_count倍(創建其自身的散列)
  7. XOR每個迭代並將它附加到iterated_block $(XOR前一哈希到當前)
  8. XOR循環結束
  9. 追加$ iterated_block至$鍵每個塊
  10. 塊循環結束
  11. 回報的關鍵

我覺得這可能是做到這一點的最好辦法。也許我太偏執了?