文章目录 [+]
烦躁的开始
因为项目一直是前后端分离,这样可以有效的方便的服务ios、Android、web端,但是就涉及到一个问题,接口加密的问题,苦思冥想之后,于是开始了采坑的路线。
我们采用了请求前签名认证,和请求到数据之后参数加密的方式来保证安全,这里主要说请求后的加密。
linux生成私钥和公钥
生成私钥:
openssl genrsa -out rsa_private_key.pem 1024
生成公钥:
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
php加密
因为js无法用公钥解密(或未找到适合的方法),所以php只能用公钥进行加密,客户端使用私钥进行解密,这里有一个大坑,就是加密参数长度的问题,如果长度太长,则会导致加密失败,下边上代码。
$data = [ 'name' => '杨宇辉', 'tel' => 15033610274, 'sex' => '男' ]; $data = json_encode($data);//转为字符串 $rsa_public = ' -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmkANmC849IOntYQQdSgLvMMGm 8V/u838ATHaoZwvweoYyd+/7Wx+bx5bdktJb46YbqS1vz3VRdXsyJIWhpNcmtKhY inwcl83aLtzJeKsznppqMyAIseaKIeAm6tT8uttNkr2zOymL/PbMpByTQeEFlyy1 poLBwrol0F4USc+owwIDAQAB -----END PUBLIC KEY----- '; $key = openssl_pkey_get_public ( $rsa_public ); if ( ! $key ) { throw new \Exception ( '公钥不可用' ); } $result = str_split ( $data , 117 );//加密最大长度只能为117,所以以117来截取 $str = ''; foreach ( $result as $v ) { openssl_public_encrypt ( $v , $crypted , $key ); $str .= $crypted; } if ( ! $str ) { throw new \Exception ( '加密失败,请检查RSA公钥' ); } $result = base64_encode ( $str ); echo $result;
js解密(其他客户端自行解密方式)
这里解密用的是JSEncrypt,比较成熟的了,但是因为某种问题,里面没有分块解密的方法,于是自能自己添加一个,从网上找一个这个js,让后打开,将下边代码加入进去:
/** * 长文本解密 * @param {string} string 加密后的base64编码 * @returns {string} 解密后的原文 * */ JSEncrypt.prototype.decryptLong = function (string) { var k = this.getKey(); var maxLength = 128; try { var string = b64tohex(string); var ct = ""; if (string.length > maxLength * 2) { var lt = string.match(/.{1,256}/g); //128位解密。取256位 lt.forEach(function (entry) { var t1 = k.decrypt(entry); ct += t1; }); return ct; } var y = k.decrypt(string); return y; } catch (ex) { return false; } };
然后使用方法如下,也是进行分块解密的:
var private_key = '\n' + '-----BEGIN PRIVATE KEY-----\n' + 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKaQA2YLzj0g6e1h\n' + 'BB1KAu8wwabxX+7zfwBMdqhnC/B6hjJ37/tbH5vHlt2S0lvjphupLW/PdVF1ezIk\n' + 'haGk1ya0qFiKfByXzdou3Ml4qzOemmozIAix5ooh4Cbq1Py6202SvbM7KYv89syk\n' + 'HJNB4QWXLLWmgsHCuiXQXhRJz6jDAgMBAAECgYAIF5cSriAm+CJlVgFNKvtZg5Tk\n' + '93UhttLEwPJC3D7IQCuk6A7Qt2yhtOCvgyKVNEotrdp3RCz++CY0GXIkmE2bj7i0\n' + 'fv5vT3kWvO9nImGhTBH6QlFDxc9+p3ukwsonnCshkSV9gmH5NB/yFoH1m8tck2Gm\n' + 'BXDj+bBGUoKGWtQ7gQJBANR/jd5ZKf6unLsgpFUS/kNBgUa+EhVg2tfr9OMioWDv\n' + 'MSqzG/sARQ2AbO00ytpkbAKxxKkObPYsn47MWsf5970CQQDIqRiGmCY5QDAaejW4\n' + 'HbOcsSovoxTqu1scGc3Qd6GYvLHujKDoubZdXCVOYQUMEnCD5j7kdNxPbVzdzXll\n' + '9+p/AkEAu/34iXwCbgEWQWp4V5dNAD0kXGxs3SLpmNpztLn/YR1bNvZry5wKew5h\n' + 'z1zEFX+AGsYgQJu1g/goVJGvwnj/VQJAOe6f9xPsTTEb8jkAU2S323BG1rQFsPNg\n' + 'jY9hnWM8k2U/FbkiJ66eWPvmhWd7Vo3oUBxkYf7fMEtJuXu+JdNarwJAAwJK0YmO\n' + 'LxP4U+gTrj7y/j/feArDqBukSngcDFnAKu1hsc68FJ/vT5iOC6S7YpRJkp8egj5o\n' + 'pCcWaTO3GgC5Kg==\n' + '-----END PRIVATE KEY-----\n'; var decrypt = new JSEncrypt (); decrypt.setPrivateKey ( private_key ); var uncrypted = decrypt.decryptLong ( data ); if ( !uncrypted || uncrypted.indexOf('null')) { alert('请求出错'); throw '请求出错'; } console.log(uncrypted);
发表评论