加密演算法中的加鹽值
在應用中,出於到安全的考慮和資料的保密,需要使用到加密演算法,有時候為了讓加密的的結果更加撲朔迷離神鬼莫測一些,常常會給被加密的資料加點“鹽”。說白了,鹽就是一串數字,完全是自己定義的,不多說,上例項。
/** * 獲取當前使用者鹽 * * @param string $extraKey 額外金鑰 * @return string */ public function getSalt($extraKey = null) { // 今天凌晨5點以後~第二天凌晨5點前 if (date('G') >= 5) { $dateString = date('md'); } // 今天凌晨5點前 // 日期標示符仍用昨天的 else { $dateString = date('md', strtotime('-1 day')); } return md5('VoyageMobile:' . $dateString . ':' . $this->_uid . ':' . $extraKey); }
這就是我們程式中,使用的一個生成鹽值的函式,這函式的返回值就是所謂的鹽值,請注意這個函式的命名,哈哈。 函式的使用如下:
/** * 加密 * * @param string $content 待加密內容 * @param string $extraKey 額外金鑰 * @return string */ public function encrypt($content, $extraKey = null) { return Helper_Cryption_Rijndael::encrypt($content, $this->getSalt($extraKey)); }
為什麼我們要使用鹽值。在回答這個問題之前,我們討論一下加密演算法,常用的加密演算法大致分為兩種:可逆和不可逆,如MD5()不可逆。RijnDael可逆。
在不可逆的加密演算法中,加鹽值通常是“錦上添花”,因為類似於Md5()這樣的演算法已經夠用了,如果還擔心的會被暴力破解的話,可加點鹽。 如:
md5('VoyageMobile:' . $this->getSalt($extraKey));
重點是在可逆的演算法中使用加鹽值。
在我們的遊戲中,我們需要對使用者ID即UID使用可逆演算法加密,為什麼呢,如果不加密會很危險,例如,其它玩家獲取到你的UID可以重複攻擊你,或者改一下UID就可以攻擊其他玩家,在造船廠,改一下船的ID,如果後臺不驗證,就可以隨意造船了,這就是串號攻擊。還有一個特殊的情況,如果我知道了一個裝備的ID,如果這個裝備恰好是贈品,不能在商店出售,
這個時候就要對ID加密了,而且還是可逆的,因為我需要知道你將要攻擊誰,購買什麼裝備,對吧。這個時候或許加鹽的必要性還是沒有體現出來,因為我對ID加密就比較安全了,這樣就可以防止串號了,何必還有一個加鹽值。
請注意,會有這樣的情況,在活動模組中,我得到一個裝備,我雖然不知道itemId,當是我知道了這個裝備ID加密後的一串數字。然後我就去拿這個數字去商店裡面購買這個裝備,而這個裝備又是不能購買的。在資料庫中,我們把不能購買的裝備的價格設定為0,並且和能購買的裝備放在一個表中。 注意,這樣的設計導致我能夠購買到這個裝備,而且一毛錢不花!
怎樣解決這個問題,我們就需要加鹽了。思路就是,在活動模組中,給所有的裝備加密使用鹽值,在商店模組中,也給所有的裝備加鹽,使用不同的鹽值。這樣的結果就是同一個裝備,在不同的模組itemId也是不同的。
在後臺也需要加一個判斷,這個裝備是否能購買!
這就是加鹽的一個好處。
需要注意點:
保證鹽值的唯一行,在我們遊戲中,通常會使用到玩家UID造鹽,這樣,不同的玩家看到的加密後的字串也不一樣。
保證鹽值的時效性,這也是出於安全的考慮,經常換鹽值,這樣加密後的字串也是變動的,不容易找到規律。