一个菜鸟驿站!

JSEncrypt和openssl_public_encrypt,php RSA加密和js解密

PHP 2019-05-15 浏览(2905) 评论(0)
- N +

文章目录 [+]

烦躁的开始

因为项目一直是前后端分离,这样可以有效的方便的服务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);


标签:
作者:猫巷

,

评论列表 (0)条评论

发表评论

召唤伊斯特瓦尔