MD5數字簽名算法:生成簽名和驗籤(附代碼)

一.背景

   爲了增加接口的安全性(防止中間人攻擊),現增加簽名算法。此算法參考微信支付中的簽名算法,由於該簽名針對前後端,採用了對稱算法,如後續接口供給多家第三方接口使用可採用非對稱算法。大致整理文檔供後續開發人員使用閱讀。

二.  簽名生成步驟

①設所有發送或者接收到的數據爲集合M,將集合M內非空參數值的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

注意如下規則:

◆參數名ASCII碼從小到大排序(字典序);

◆如果參數的值爲空不參與簽名;

◆參數名區分大小寫;

◆驗證調用返回或主動通知簽名時,傳送的sign參數不參與簽名,將生成的簽名與該sign值作校驗。

②在stringA最後拼接上key(密鑰)得到stringSignTemp字符串,並對stringSignTemp進行MD5運算,再將得到的字符串所有字符轉換爲大寫,得到sign值signValue。

樣例:假設傳送的參數如下:

第一步:對參數按照key=value的格式,並按照參數名ASCII字典序排序如下

stringA = "MEMBER_ID=1&body=test&mch_id=1&order_id=20";

第二步:拼接API密鑰(比如key:192006250b4c09247ec02edce69f6a2d)

stringSignTemp = stringA+"&key=192006250b4c09247ec02edce69f6a2d" //注:key爲密鑰

signValue = md5(stringSignTemp).toUpperCase(); //用MD5加密完後,並且都轉爲大寫

最終打包的數據爲(可以就拿這組數據測試):

{"MEMBER_ID":1,"body":"test","mch_id":1,"order_id":20,"sign":4AC10199EFB3D9BF4959DFEA83900ACA}

三.  下面是我整理的JS生成簽名的代碼,php驗證簽名的代碼

//JS生成簽名源碼
<script src="md5.min.js"></script> //這個網上自己下載
<script>

    var paramsObj = { order_id: 20, mch_id: 1, body: 'test', MEMBER_ID: 1 };//要傳的參數(測試數據)
    var key = '192006250b4c09247ec02edce69f6a2d'; //密鑰
    var sign = getSign(paramsObj); //獲取簽名sign
    console.log(sign);  //輸出簽名

    function getSign(params) {
        var arr = [];
        for (var i in params) {
            arr.push((i + "=" + params[i]));
        }
        return paramsStrSort(arr.join(("&")));
    }

    function paramsStrSort(paramsStr) {
        var urlStr = paramsStr.split("&").sort().join("&");
        var newUrl = urlStr + '&key=' + key;
        return md5(newUrl).toUpperCase();
    }

</script>
//php服務端驗證簽名源碼
<?php

class Sign
{
    public $key = '192006250b4c09247ec02edce69f6a2d'; //密鑰

    /**
     * 驗籤
     * @param $params
     * @return bool
     */
    public function validateSign($params) {
        $stringA = $this->paramFilter($params);
        $sign = $this->md5Sign($stringA);
        if(!isset($params['sign']) || empty($params['sign']) || $params['sign'] != $sign) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 除去數組中的空值和簽名參數
     * @param $param
     * @return array 去掉空值與簽名參數後的新簽名參數組
     */
    function paramFilter($param) {
        $para_filter = array();
        while (list ($key, $val) = each ($param)) {
            if($key == "sign"  || $val == "") continue;
            else    $para_filter[$key] = $param[$key];
        }
        return $this->argSort($para_filter);
    }

    /**
     * 對數組排序
     * @param $param
     * @return mixed 排序後的數組
     */
    function argSort($param) {
        ksort($param);
        reset($param);
        return $this->createLinkString($param);
    }

    /**
     * 把數組所有元素,按照“參數=參數值”的模式用“&”字符拼接成字符串
     * @param $para
     * @return bool|string 拼接完成以後的字符串
     */
    function createLinkString($para) {
        $arg  = "";
        while (list ($key, $val) = each ($para)) {
            $arg.=$key."=".$val."&";
        }
        //去掉最後一個&字符
        $arg = substr($arg,0,count($arg)-2);
        //如果存在轉義字符,那麼去掉轉義
        if(get_magic_quotes_gpc()){
            $arg = stripslashes($arg);
        }
        $arg = $arg.'&key='.$this->key;
        return $arg;
    }

    /**
     * 生成md5簽名字符串
     * @param $preStr string 需要簽名的字符串
     * @return string 簽名結果
     */
    function md5Sign($preStr) {
        return strtoupper(md5($preStr));
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章