1. 程式人生 > >加密演算法中的加鹽值

加密演算法中的加鹽值

在應用中,出於到安全的考慮和資料的保密,需要使用到加密演算法,有時候為了讓加密的的結果更加撲朔迷離神鬼莫測一些,常常會給被加密的資料加點“鹽”。說白了,鹽就是一串數字,完全是自己定義的,不多說,上例項。

    /**
     * 獲取當前使用者鹽
     *
     * @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,如果這個裝備恰好是贈品,不能在商店出售,

我可以偽造一個URL請求購買,這個時候,後臺判斷這個商品確實存在(因為它是贈品),所以可能購買成功。

這個時候就要對ID加密了,而且還是可逆的,因為我需要知道你將要攻擊誰,購買什麼裝備,對吧。這個時候或許加鹽的必要性還是沒有體現出來,因為我對ID加密就比較安全了,這樣就可以防止串號了,何必還有一個加鹽值。

請注意,會有這樣的情況,在活動模組中,我得到一個裝備,我雖然不知道itemId,當是我知道了這個裝備ID加密後的一串數字。然後我就去拿這個數字去商店裡面購買這個裝備,而這個裝備又是不能購買的。在資料庫中,我們把不能購買的裝備的價格設定為0,並且和能購買的裝備放在一個表中。 注意,這樣的設計導致我能夠購買到這個裝備,而且一毛錢不花!

怎樣解決這個問題,我們就需要加鹽了。思路就是,在活動模組中,給所有的裝備加密使用鹽值,在商店模組中,也給所有的裝備加鹽,使用不同的鹽值。這樣的結果就是同一個裝備,在不同的模組itemId也是不同的。

在後臺也需要加一個判斷,這個裝備是否能購買!

這就是加鹽的一個好處。

需要注意點:

保證鹽值的唯一行,在我們遊戲中,通常會使用到玩家UID造鹽,這樣,不同的玩家看到的加密後的字串也不一樣。

保證鹽值的時效性,這也是出於安全的考慮,經常換鹽值,這樣加密後的字串也是變動的,不容易找到規律。