PHP hash 介面對接

蘇生不惑發表於2019-02-16

最近接一個專案,需要呼叫對方介面生成 token 但只提供了 node 版,原始碼如下

//https://blog.zhengxianjun.com/2015/05/javascript-crypto-js/
npm install crypto-js
var CryptoJS = require(`crypto-js`)
calSignature = function (toSign, key) {
        var hash, hex, signed;
        hash = CryptoJS.HmacSHA1(toSign, key);
        hex = hash.toString(CryptoJS.enc.Hex);
        signed = base64.encodeBase64(hex);
        return signed;
    };

var hmacSHA1 = CryptoJS.HmacSHA1("Message", "Secret Passphrase").toString(CryptoJS.enc.Hex);
console.log(hmacSHA1) ;//e90f713295ea4cc06c92c9248696ffafc5d01faf 
也可以線上測試 https://blog.zhengxianjun.com/online-tool/hash/

<script src="cryptojs/rollups/md5.js"></script>
var str = `123456`;
CryptoJS.MD5(str);
<script src="cryptojs/rollups/hmac-sha1.js">
</script>
<script src="cryptojs/rollups/hmac-sha3.js">
</script>
<script src="cryptojs/rollups/hmac-sha224.js">
</script>
<script src="cryptojs/rollups/hmac-sha256.js">
</script>
var str = `123456`;
var password = `password`;
 
// Hmac 相關呼叫前都增加了 Hmac
CryptoJS.HmacMD5(str, password);
CryptoJS.HmacRIPEMD160(str, password);
CryptoJS.HmacSHA1(str, password);

但是我們的專案是基於 PHP 於是有了

$sign = base64_encode(hash_hmac(`sha1`, $sign, $key)); 

果然 PHP 是最好的語言,一句話搞定。

另外說到請求對方介面的問題,對方要求傳遞一個 json 引數過去,比如

$url = `xxxxx.com`;
$data = [`limit` => [`start` => 0, `end` => 5]];
$res = curlGet($url.`/api/?`.json_encode($data);

結果提示 fail Malformed HTTP request line
但是 python get 沒問題

res = requests.get(url, params=data, headers=headers)

於是對引數再進行一次 base64

$res =curlGet($url.`/api/?`.base64_encode(json_encode($data));

但對方有時候接受的引數 base64 解析出錯

>>> s=`eyJsaW1pdCI6eyJzdGFydCI6MCwiZW5kIjo1fSwidGFibGVfbmFtZSI6Im9ubGluZV91dl9hY
2NvdW50X2lkXzFob3VyX2FuYWx5c2lzX2RhdGEiLCJmaWx0ZXJfYXJncyI6eyJ2ZmlkIjoiMTQiLCJ0a
W1lc3RhbXBfMWhvdXIiOiIyMDE4LTAxLTA1IDIwOjA0OjI2In0sImJpel9kZXMwMSI6MCwib3JkZXJfY
nkiOiJ0aW1lc3RhbXBfMWhvdXIifQ`
>>> base64.b64decode(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "d:python27libase64.py", line 76, in b64decode
    raise TypeError(msg)
TypeError: Incorrect padding
>>> base64.b64decode(s+`===`)
`{"limit":{"start":0,"end":5}`
於是有了如下處理
def decode_base64(data):
    missing_padding = len(data) % 4
    if missing_padding != 0:
        data += b`=`* (4 - missing_padding)
    return base64.decodestring(data)

傳遞時也改成 安全 base64

function urlsafe_b64encode($string) {
   $data = base64_encode($string);
   $data = str_replace(array(`+`,`/`,`=`),array(`-`,`_`,``),$data);
   return $data;
 }
function urlsafe_b64decode($string) {
   $data = str_replace(array(`-`,`_`),array(`+`,`/`),$string);
   $mod4 = strlen($data) % 4;
   if ($mod4) {
       $data .= substr(`====`, $mod4);
   }
   return base64_decode($data);
 }

$res =curlGet($url.`/api/?`.urlsafe_b64encode(json_encode($data));

相關文章