Skip to content

Instantly share code, notes, and snippets.

@wilsoncook
Last active November 3, 2016 03:36
Show Gist options
  • Save wilsoncook/cb2aefd4ba4c86ab16ab to your computer and use it in GitHub Desktop.
Save wilsoncook/cb2aefd4ba4c86ab16ab to your computer and use it in GitHub Desktop.
极简的服务器HTTP通信加密---PHP/JS端
/**
* 通用通信加密验证库【注:传递的参数名仅支持:数字、大小写字母】
* @author Wilson Zeng jackzcs@gmail.com
* @version 0.0.1
*/
(function () {
// Establish the root object, `window` in the browser, or `exports` on the server.
var root = this;
//依赖自由的md5
//if (typeof(md5) !== 'function') function md5(e){var t;var n=function(e,t){return e<<t|e>>>32-t};var r=function(e,t){var n,r,i,s,o;i=e&2147483648;s=t&2147483648;n=e&1073741824;r=t&1073741824;o=(e&1073741823)+(t&1073741823);if(n&r){return o^2147483648^i^s}if(n|r){if(o&1073741824){return o^3221225472^i^s}else{return o^1073741824^i^s}}else{return o^i^s}};var i=function(e,t,n){return e&t|~e&n};var s=function(e,t,n){return e&n|t&~n};var o=function(e,t,n){return e^t^n};var u=function(e,t,n){return t^(e|~n)};var a=function(e,t,s,o,u,a,f){e=r(e,r(r(i(t,s,o),u),f));return r(n(e,a),t)};var f=function(e,t,i,o,u,a,f){e=r(e,r(r(s(t,i,o),u),f));return r(n(e,a),t)};var l=function(e,t,i,s,u,a,f){e=r(e,r(r(o(t,i,s),u),f));return r(n(e,a),t)};var c=function(e,t,i,s,o,a,f){e=r(e,r(r(u(t,i,s),o),f));return r(n(e,a),t)};var h=function(e){var t;var n=e.length;var r=n+8;var i=(r-r%64)/64;var s=(i+1)*16;var o=new Array(s-1);var u=0;var a=0;while(a<n){t=(a-a%4)/4;u=a%4*8;o[t]=o[t]|e.charCodeAt(a)<<u;a++}t=(a-a%4)/4;u=a%4*8;o[t]=o[t]|128<<u;o[s-2]=n<<3;o[s-1]=n>>>29;return o};var p=function(e){var t="",n="",r,i;for(i=0;i<=3;i++){r=e>>>i*8&255;n="0"+r.toString(16);t=t+n.substr(n.length-2,2)}return t};var d=[],v,m,g,y,b,w,E,S,x,T=7,N=12,C=17,k=22,L=5,A=9,O=14,M=20,_=4,D=11,P=16,H=23,B=6,j=10,F=15,I=21;e=this.utf8_encode(e);d=h(e);w=1732584193;E=4023233417;S=2562383102;x=271733878;t=d.length;for(v=0;v<t;v+=16){m=w;g=E;y=S;b=x;w=a(w,E,S,x,d[v+0],T,3614090360);x=a(x,w,E,S,d[v+1],N,3905402710);S=a(S,x,w,E,d[v+2],C,606105819);E=a(E,S,x,w,d[v+3],k,3250441966);w=a(w,E,S,x,d[v+4],T,4118548399);x=a(x,w,E,S,d[v+5],N,1200080426);S=a(S,x,w,E,d[v+6],C,2821735955);E=a(E,S,x,w,d[v+7],k,4249261313);w=a(w,E,S,x,d[v+8],T,1770035416);x=a(x,w,E,S,d[v+9],N,2336552879);S=a(S,x,w,E,d[v+10],C,4294925233);E=a(E,S,x,w,d[v+11],k,2304563134);w=a(w,E,S,x,d[v+12],T,1804603682);x=a(x,w,E,S,d[v+13],N,4254626195);S=a(S,x,w,E,d[v+14],C,2792965006);E=a(E,S,x,w,d[v+15],k,1236535329);w=f(w,E,S,x,d[v+1],L,4129170786);x=f(x,w,E,S,d[v+6],A,3225465664);S=f(S,x,w,E,d[v+11],O,643717713);E=f(E,S,x,w,d[v+0],M,3921069994);w=f(w,E,S,x,d[v+5],L,3593408605);x=f(x,w,E,S,d[v+10],A,38016083);S=f(S,x,w,E,d[v+15],O,3634488961);E=f(E,S,x,w,d[v+4],M,3889429448);w=f(w,E,S,x,d[v+9],L,568446438);x=f(x,w,E,S,d[v+14],A,3275163606);S=f(S,x,w,E,d[v+3],O,4107603335);E=f(E,S,x,w,d[v+8],M,1163531501);w=f(w,E,S,x,d[v+13],L,2850285829);x=f(x,w,E,S,d[v+2],A,4243563512);S=f(S,x,w,E,d[v+7],O,1735328473);E=f(E,S,x,w,d[v+12],M,2368359562);w=l(w,E,S,x,d[v+5],_,4294588738);x=l(x,w,E,S,d[v+8],D,2272392833);S=l(S,x,w,E,d[v+11],P,1839030562);E=l(E,S,x,w,d[v+14],H,4259657740);w=l(w,E,S,x,d[v+1],_,2763975236);x=l(x,w,E,S,d[v+4],D,1272893353);S=l(S,x,w,E,d[v+7],P,4139469664);E=l(E,S,x,w,d[v+10],H,3200236656);w=l(w,E,S,x,d[v+13],_,681279174);x=l(x,w,E,S,d[v+0],D,3936430074);S=l(S,x,w,E,d[v+3],P,3572445317);E=l(E,S,x,w,d[v+6],H,76029189);w=l(w,E,S,x,d[v+9],_,3654602809);x=l(x,w,E,S,d[v+12],D,3873151461);S=l(S,x,w,E,d[v+15],P,530742520);E=l(E,S,x,w,d[v+2],H,3299628645);w=c(w,E,S,x,d[v+0],B,4096336452);x=c(x,w,E,S,d[v+7],j,1126891415);S=c(S,x,w,E,d[v+14],F,2878612391);E=c(E,S,x,w,d[v+5],I,4237533241);w=c(w,E,S,x,d[v+12],B,1700485571);x=c(x,w,E,S,d[v+3],j,2399980690);S=c(S,x,w,E,d[v+10],F,4293915773);E=c(E,S,x,w,d[v+1],I,2240044497);w=c(w,E,S,x,d[v+8],B,1873313359);x=c(x,w,E,S,d[v+15],j,4264355552);S=c(S,x,w,E,d[v+6],F,2734768916);E=c(E,S,x,w,d[v+13],I,1309151649);w=c(w,E,S,x,d[v+4],B,4149444226);x=c(x,w,E,S,d[v+11],j,3174756917);S=c(S,x,w,E,d[v+2],F,718787259);E=c(E,S,x,w,d[v+9],I,3951481745);w=r(w,m);E=r(E,g);S=r(S,y);x=r(x,b)}var q=p(w)+p(E)+p(S)+p(x);return q.toLowerCase()}
var md5=(function(){function e(e,t){var o=e[0],u=e[1],a=e[2],f=e[3];o=n(o,u,a,f,t[0],7,-680876936);f=n(f,o,u,a,t[1],12,-389564586);a=n(a,f,o,u,t[2],17,606105819);u=n(u,a,f,o,t[3],22,-1044525330);o=n(o,u,a,f,t[4],7,-176418897);f=n(f,o,u,a,t[5],12,1200080426);a=n(a,f,o,u,t[6],17,-1473231341);u=n(u,a,f,o,t[7],22,-45705983);o=n(o,u,a,f,t[8],7,1770035416);f=n(f,o,u,a,t[9],12,-1958414417);a=n(a,f,o,u,t[10],17,-42063);u=n(u,a,f,o,t[11],22,-1990404162);o=n(o,u,a,f,t[12],7,1804603682);f=n(f,o,u,a,t[13],12,-40341101);a=n(a,f,o,u,t[14],17,-1502002290);u=n(u,a,f,o,t[15],22,1236535329);o=r(o,u,a,f,t[1],5,-165796510);f=r(f,o,u,a,t[6],9,-1069501632);a=r(a,f,o,u,t[11],14,643717713);u=r(u,a,f,o,t[0],20,-373897302);o=r(o,u,a,f,t[5],5,-701558691);f=r(f,o,u,a,t[10],9,38016083);a=r(a,f,o,u,t[15],14,-660478335);u=r(u,a,f,o,t[4],20,-405537848);o=r(o,u,a,f,t[9],5,568446438);f=r(f,o,u,a,t[14],9,-1019803690);a=r(a,f,o,u,t[3],14,-187363961);u=r(u,a,f,o,t[8],20,1163531501);o=r(o,u,a,f,t[13],5,-1444681467);f=r(f,o,u,a,t[2],9,-51403784);a=r(a,f,o,u,t[7],14,1735328473);u=r(u,a,f,o,t[12],20,-1926607734);o=i(o,u,a,f,t[5],4,-378558);f=i(f,o,u,a,t[8],11,-2022574463);a=i(a,f,o,u,t[11],16,1839030562);u=i(u,a,f,o,t[14],23,-35309556);o=i(o,u,a,f,t[1],4,-1530992060);f=i(f,o,u,a,t[4],11,1272893353);a=i(a,f,o,u,t[7],16,-155497632);u=i(u,a,f,o,t[10],23,-1094730640);o=i(o,u,a,f,t[13],4,681279174);f=i(f,o,u,a,t[0],11,-358537222);a=i(a,f,o,u,t[3],16,-722521979);u=i(u,a,f,o,t[6],23,76029189);o=i(o,u,a,f,t[9],4,-640364487);f=i(f,o,u,a,t[12],11,-421815835);a=i(a,f,o,u,t[15],16,530742520);u=i(u,a,f,o,t[2],23,-995338651);o=s(o,u,a,f,t[0],6,-198630844);f=s(f,o,u,a,t[7],10,1126891415);a=s(a,f,o,u,t[14],15,-1416354905);u=s(u,a,f,o,t[5],21,-57434055);o=s(o,u,a,f,t[12],6,1700485571);f=s(f,o,u,a,t[3],10,-1894986606);a=s(a,f,o,u,t[10],15,-1051523);u=s(u,a,f,o,t[1],21,-2054922799);o=s(o,u,a,f,t[8],6,1873313359);f=s(f,o,u,a,t[15],10,-30611744);a=s(a,f,o,u,t[6],15,-1560198380);u=s(u,a,f,o,t[13],21,1309151649);o=s(o,u,a,f,t[4],6,-145523070);f=s(f,o,u,a,t[11],10,-1120210379);a=s(a,f,o,u,t[2],15,718787259);u=s(u,a,f,o,t[9],21,-343485551);e[0]=m(o,e[0]);e[1]=m(u,e[1]);e[2]=m(a,e[2]);e[3]=m(f,e[3])};function t(e,t,n,r,i,s){t=m(m(t,e),m(r,s));return m(t<<i|t>>>32-i,n)};function n(e,n,r,i,s,o,u){return t(n&r|~n&i,e,n,s,o,u)};function r(e,n,r,i,s,o,u){return t(n&i|r&~i,e,n,s,o,u)};function i(e,n,r,i,s,o,u){return t(n^r^i,e,n,s,o,u)};function s(e,n,r,i,s,o,u){return t(r^(n|~i),e,n,s,o,u)};function o(t){var n=t.length,r=[1732584193,-271733879,-1732584194,271733878],i;for(i=64;i<=t.length;i+=64){e(r,u(t.substring(i-64,i)))};t=t.substring(i-64);var s=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(i=0;i<t.length;i++)s[i>>2]|=t.charCodeAt(i)<<(i%4<<3);s[i>>2]|=128<<(i%4<<3);if(i>55){e(r,s);for(i=0;i<16;i++)s[i]=0};s[14]=n*8;e(r,s);return r};function u(e){var t=[],n;for(n=0;n<64;n+=4){t[n>>2]=e.charCodeAt(n)+(e.charCodeAt(n+1)<<8)+(e.charCodeAt(n+2)<<16)+(e.charCodeAt(n+3)<<24)};return t};function c(e){var t="",n=0;for(;n<4;n++)t+=a[e>>n*8+4&15]+a[e>>n*8&15];return t};function h(e){for(var t=0;t<e.length;t++)e[t]=c(e[t]);return e.join("")};function d(e){return h(o(unescape(encodeURIComponent(e))))};function m(e,t){return e+t&4294967295};var a="0123456789abcdef".split("");return d})();
//获取一个字符串的ascii值的和
function getStrAscii (str) {
var sum = 0;
for (var i = 0; i < str.length; i ++) { sum += (str + '').charCodeAt(i); }
return sum;
}
//通过ascii码值的和来排序(升序)一维数组
function sortAscii (arr) {
var map = {}, __getCacheAscii = function (key) { return typeof map[key] == 'undefined' ? (map[key] = getStrAscii(key)) : map[key]; }; //获取一个字符串$key的ascii码和,并缓存
for (var i = 0; i < arr.length; i++) {
var sumI = __getCacheAscii(arr[i]);
for (var j = i + 1; j < arr.length; j++) {
var sumJ = __getCacheAscii(arr[j]);
if (sumJ < sumI) { var tmp = arr[j]; arr[j] = arr[i]; arr[i] = tmp; }
}
}
return arr;
}
function isArray (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
//将hash型params使用PHP的sort算法排序,返回数组
//exclude=参数排除列表
function sortParams (params, exclude) {
if (exclude) { for (var i = 0; i < exclude.length; i++) { delete params[exclude[i]]; } }
var keys = [];
for (var key in params) { keys.push(key); }
sortAscii(keys);
var ret = [];
for (var i = 0; i < keys.length; i ++) { ret.push(params[keys[i]]); }
return ret;
}
var SignAuther = {
/**
* 通信验证
* 算法:sign = md5(md5(substr(timeline, -5)) + md5(参数值1 + 参数值2 + ... + key))
* @param array $params 参数值列表(按顺序,若为hash表,则将自动sort后转换)
* @param [type] $sign 签名
* @param [type] $timeline 通信时间线
* @param [type] $key 加密密钥
* @param [type] $expire 请求过期时限(秒)
* @return bool [description]
*/
check: function (p) {
p || (p = {});
p['params'] || (p['params'] = []);
p['sign'] || (p['sign'] = '');
p['timeline'] = parseInt(p['timeline']) || 0;
p['key'] || (p['key'] = '');
p['expire'] = parseInt(p['expire']) || 5;
//---参数处理
if (typeof(p['params']) == 'string') p['params'] = [p['params']];
//是hash表,转换为数组,并排除timeline,sign
if (!isArray(p['params'])) p['params'] = sortParams(p['params'], ['timeline', 'sign']);
//---参数值字符串拼接
var paramStr = p['params'].join('');
//---组合sign
var curSign = md5(md5((p['timeline'] + '').slice(-5)) + md5(paramStr + p['key']));
if (Math.floor(Date.now() / 1000) > (p['timeline'] + p['expire']) || (curSign !== p['sign'])) {
return false;
}
return true;
},
/**
* 构建通信sign
* 算法:sign = md5(md5(substr(timeline, -5)) + md5(参数值1 + 参数值2 + ... + key))
* @param array $params 参数值列表(按顺序,若为hash表,则将自动sort后转换)
* @param [type] $key 加密密钥
* @param [type] $timeline 默认为当前时间
* @return array('timeline' => 时间戳, 'sign' => sign)
*/
build: function (p) {
p || (p = {});
p['params'] || (p['params'] = []);
p['timeline'] = parseInt(p['timeline']) || Math.floor(Date.now() / 1000);
p['key'] || (p['key'] = '');
//---参数处理
if (typeof(p['params']) == 'string') p['params'] = [p['params']];
//是hash表,转换为数组,并排除timeline,sign
if (!isArray(p['params'])) p['params'] = sortParams(p['params'], ['timeline', 'sign']);
//---参数值字符串拼接
var paramStr = p['params'].join('');
// console.log('----------BUILD', (p['timeline'] + '').slice(-5), paramStr + p['key'], md5((p['timeline'] + '').slice(-5)), md5(paramStr + p['key']));
return {
'timeline': p['timeline'],
'sign': md5(md5((p['timeline'] + '').slice(-5)) + md5(paramStr + p['key']))
};
}
};
//暴露到所处环境
if (typeof(module) !== 'undefined') {
module.exports = SignAuther;
} else {
root.SignAuther = SignAuther;
}
}).call(this);
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* 通用通信加密验证库【注:传递的参数名仅支持:数字、大小写字母】
* @author Wilson Zeng jackzcs@gmail.com
* @version 0.0.1
*/
class SignAuther {
//判断是否是关联数组
public static function isAssoc($arr) {
return array_keys($arr) !== range(0, count($arr) - 1);
}
//获取一个字符串的ascii值的和
public static function getStrAscii ($str) {
$sum = 0;
for ($i = 0; $i < strlen($str); $i ++) { $sum += ord($str[$i]); }
return $sum;
}
//通过ascii码值的和来排序(升序)一维数组
public static function sortAscii (&$arr) {
$count = count($arr);
$map = array();
for ($i = 0; $i < $count; $i++) {
$sumI = SignAuther::__getCacheAscii($map, $arr[$i]);
for ($j = $i + 1; $j < $count; $j++) {
$sumJ = SignAuther::__getCacheAscii($map, $arr[$j]);
if ($sumJ < $sumI) {
$tmp = $arr[$j];
$arr[$j] = $arr[$i];
$arr[$i] = $tmp;
}
}
}
return $arr;
}
//获取一个字符串$key的ascii码和,并缓存
public static function __getCacheAscii (&$map, $key) {
if (!isset($map[$key])) { $map[$key] = SignAuther::getStrAscii($key); }
return $map[$key];
}
//将hash型params使用PHP的sort算法排序,返回数组
//$exclude=参数排除列表
public static function sortParams($params, $exclude) {
if ($exclude) { foreach ($exclude as $ekey) { unset($params[$ekey]); } }
$keys = array_keys($params);
SignAuther::sortAscii($keys);
$ret = array();
foreach ($keys as $key) { $ret[] = $params[$key]; }
return $ret;
}
/**
* 通信验证
* 算法:sign = md5(md5(substr(timeline, -5)) + md5(参数值1 + 参数值2 + ... + key))
* @param array $params 参数值列表(按顺序,若为hash表,则将自动sort后转换)
* @param [type] $sign 签名
* @param [type] $timeline 通信时间线
* @param [type] $key 加密密钥
* @param [type] $expire 请求过期时限(秒)
* @return bool [description]
*/
public static function check ($p) {
$p = array_merge(array(
'params' => array(), //参数值列表(按顺序)
'sign' => '',
'timeline' => 0,
'key' => '',
'expire' => 5,
), (array)$p);
//---参数处理
if (is_string($p['params'])) $p['params'] = array($p['params']);
//是hash表,转换为数组,并排除timeline,sign
if (self::isAssoc($p['params'])) $p['params'] = self::sortParams($p['params'], array('timeline', 'sign'));
//---参数值字符串拼接
$paramStr = implode('', (array)$p['params']);
//---组合sign
$curSign = md5(md5(substr($p['timeline'], -5)) . md5($paramStr . $p['key']));
// var_dump('--------CHECK', substr($p['timeline'], -5), $paramStr . $p['key'], md5(substr($p['timeline'], -5)), md5($paramStr . $p['key']));
if (time() > ($p['timeline'] + $p['expire']) || ($curSign !== $p['sign'])) {
return false;
}
return true;
}
/**
* 构建通信sign
* 算法:sign = md5(md5(substr(timeline, -5)) + md5(参数值1 + 参数值2 + ... + key))
* @param array $params 参数值列表(按顺序,若为hash表,则将自动sort后转换)
* @param [type] $key 加密密钥
* @param [type] $timeline 默认为当前时间
* @return array('timeline' => 时间戳, 'sign' => sign)
*/
public static function build ($p) {
$p = array_merge(array(
'params' => array(), //参数值列表(按顺序)
'key' => '',
'timeline' => time(),
), (array)$p);
//---参数处理
if (is_string($p['params'])) $p['params'] = array($p['params']);
//是hash表,转换为数组,并排除timeline,sign
if (self::isAssoc($p['params'])) $p['params'] = self::sortParams($p['params'], array('timeline', 'sign'));
//---参数值字符串拼接
$paramStr = implode('', (array)$p['params']);
return array(
'timeline' => $p['timeline'],
'sign' => md5(md5(substr($p['timeline'], -5)) . md5($paramStr . $p['key'])),
);
}
}
<?php
//---通信验证封装
//验证
//$data = $_POST 或 $_GET 或 $_REQUEST 或 其他,默认为$_POST
function SA_check($data) {
if (!$data) $data = &$_POST;
return SignAuther::check(array(
'params' => $data,
'key' => DDM_API_KEY,
'sign' => $data['sign'],
'timeline' => $data['timeline'],
));
}
//构建
function SA_build($data) {
return SignAuther::build(array(
'params' => $data,
'key' => DDM_API_KEY,
));
}
//针对json形式返回数据(不适合大数据)
//返回格式:
//{"data":"原始json数据base64串", "timeline":0, "sign":"ddddd"}
function safeJsonReturn($status, $message) {
$json = json_encode(array('status' => $status, 'message' => $message));
$base64 = base64_encode($json);
$ret = SA_build($base64);
exit(json_encode(array(
'data' => $base64,
'timeline' => $ret['timeline'],
'sign' => $ret['sign'],
)));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment