2013-10-12 64 views
2

我正在測試codeigniter加密庫,並且似乎無法獲得一致的結果。 我建立基本上只是有以下代碼Codeigniter加密類產生不一致的結果

$pwd = "test string"; 
    $key = "testkey_obviously_it_will_be_more_secure"; 
    for ($i=0; $i<11; $i++){ 
     echo $this->encrypt->encode($pwd, $key)."<br>"; 
    } 

的輸出是10個完全不同的字符行測試頁。

我顯然做錯了什麼,但我看不出它會是什麼。我曾嘗試使用帶有和沒有$鍵的編碼函數,但結果對我來說是一樣的。

順便說一句,我使用笨2.1.0在我的測試環境

回答

3

編碼庫按預期工作。讓我們來看看默認mcrypt_encode()方法:

function mcrypt_encode($data, $key) 
{ 
     $init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode()); 
     $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND); 
     return $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key); 
} 

注意,需要內部編碼的地方,噪聲被添加到加密的隨機因素。嘗試將您正在生成的10個密鑰存儲到數組中並解密它們。你會正確地返回你的值。

如果您正在尋找編碼嚴格單向和生產一致的結果,我建議使用PHP散列()方法(可用自5.1.2起):http://www.php.net/manual/ro/function.hash.php

生成散列的安全方式是創建一個隨機種子值,然後將其連接到用戶的密碼。這防止彩虹桌開裂和其他事情。

hash('sha512', $seed . $password); 

更新:的想法是,加密類是爲了用於能夠編碼和也解碼一些字符串。這樣想 - 這不是一個安全的例子,但它會做的理解點:你想存儲一個人的信用卡信息在您的網站上。當然,您希望保持這些信息的安全,這樣如果有人闖入數據庫,這不是什麼大問題,因爲所有信息都是加密的。當然,您也希望能夠解碼該信息並將其顯示給用戶,以防他們再次從您的網站訂購某些內容,而不是讓他們手動輸入數據,因此您還需要能夠解密該數據。

作爲一個經驗法則,我的理解是,如果加密算法是雙向的(即它可以被編碼和解碼),那麼它不像單向加密算法那樣安全(只編碼數據)。

如果您正在存儲用戶登錄憑證,則永遠不會希望能夠解碼用戶的密碼,例如,因爲這是用戶可以輕鬆重置的。你永遠不想在一個帳戶上顯示用戶的密碼,所以你總是保持鎖定。這是您使用單向加密算法的地方 - 您在創建條目時編碼一次數據,然後在數據庫中查找條目時,而不是運行類似的代碼:

SELECT * 
FROM user 
WHERE user.password = 'STAR_WARS' 
當你建立自己的帳戶

SELECT * 
FROM user 
WHERE user.password = '5badcaf789d3d1d09794d8f021f40f0e' 

以上可以通過編碼你從用戶接收第一時間的數據,來實現,然後每當你:

你會運行類似檢查登錄憑證,您只需對它們提供的字符串運行編碼算法。

至於創建一個新帳戶的工作流程:

  1. 用戶創建密碼爲「星火」的新帳戶。
  2. 用戶保存在數據庫中,密碼爲'5badcaf789d3d1d09794d8f021f40f0e',它是通過對用戶提供的密碼運行md5()而獲得的。

工作流用於認證用戶:

  1. 用戶通過登錄表單發送口令 '星球大戰'。
  2. 密碼被編碼爲'5badcaf789d3d1d09794d8f021f40f0e'。
  3. 我們檢查我們的數據庫條目,找到密碼是'5badcaf789d3d1d09794d8f021f40f0e'的地方。

在上面的系統中,我們從不存儲用戶的原始密碼 - 只有加密的數據。

現在看起來很簡單,但MD5作爲加密算法已經完全破解 - 也就是說,因爲只有很多字符串組合可能,所以大部分值都被顛倒過來了,所以黑客把' 5badcaf789d3d1d09794d8f021f40f0e',他們通過腳本運行它,列出所有映射到'5badcaf789d3d1d09794d8f021f40f0e'的可能的登錄密碼,其中我們還會發現'starwars'。

重要的是讓您的密碼生成時間儘可能不長或者模糊,但儘可能隨機。這就是爲什麼在上面的例子中,我們生成了一個種子,我們使用它來添加一個隨機元素到密碼,我們使用更強大的加密算法。

所以種子可能是字符串:'sajuh27ahjs'。

當用戶創建新帳戶時,我們將種子與其原始密碼連接起來。所以對於我們的星球大戰例如,用戶的原始密碼被加密會前:

'sajuh27ahjsstarwars' 

種子被存儲在數據庫中,沒有加密,在衆目睽睽下,我們將需要在以後進行解碼。好的,現在我們用強大的密碼加密密碼,比如SHA512。因此,我們得出:

hash('sha512', $seed . $password); 

注意這種攻擊是如何很難突破,因爲種子增加了一個隨機元素,這使得它很難爲斷路器明白的地方,我們已經放置了種子,甚至與知識,它需要爲每個可生成的特定隨機種子(這是很多)建立一個值表映射表。

希望清除一些事情,隨時可以發射更多的問題,否則!

+1

感謝您的回覆。我仍然有點困惑,但我按照你的建議做了,並將10個值放入一個數組中,並用原始字符串獎勵了10次。我猜這種方法不適合將密碼存儲到數據庫中,因爲每次均等比較都會失敗。我會研究哈希方法,看看我能否理解這一點。再次感謝! –

+0

@ o11y_75嘿,我已經用更多的信息更新了我的答案。謝謝你讓我知道你有一些不明白的地方 - 我希望這個更新能解釋更多關於這個過程的內容! –

相關問題