PHP 非对称加密 RSA接口加密

经验分享 764 浏览

PHP数据加密 RSA接口加密。

在app中,我们的app端必然是需要调用后端接口聊获取数据的。通常我们的部分敏感数据需要加密来处理。这里比较常见的就是使用rsa加密处理啦。


| 生成密钥

rsa加密需要生成公钥和私钥。一般客户端在闪屏页首次请求接口,传递设备号,生成并获取服务器端返回的公钥,然后保存公钥在客户端。服务器端也将设备号,公钥,私钥保存在数据库。以便于根据设备号可以直接查询数据库对应私钥来解密。

/**
 * 配置
 * @var array
 */
protected $_config = array(
    'RSA_TABLE' => 'it_rsa_key', //rsa表
    'RSA_UNIQUE' => 'equipment',//根据标识生成公私钥,这里取得是设备号(app为例)
    'RSA_PUBLIC_KEY' => 'public_key',//公钥字段
    'RSA_PRIVATE_KEY' => 'private_key',//私钥字段
);

/**
 * 生成密钥
 * @param string $equipment
 * @throws \Exception
 * @return string $publicKey
 */
public function generateKey($equipment){
    $sql = "select `{$this->_config['RSA_PUBLIC_KEY']}` from `{$this->_config['RSA_TABLE']}` where `{$this->_config['RSA_UNIQUE']}` = {$equipment} limit 1";
    $publicKey = Db::query($sql);
    if(!$publicKey){
        $key = openssl_pkey_new(['private_key_bits' => 2048]); #加密串长度,此处必须int型
        if(!$key){
            throw new \LogicException('生成密钥失败',1003);
        }
        openssl_pkey_export($key, $privateKey);   #提取私钥
        $arrKey = openssl_pkey_get_details($key); #生成公钥
        $publicKey = $arrKey["key"];
        $time = time();
        $sql  = "insert ignore into `{$this->_config['RSA_TABLE']}` values('','$equipment','{$publicKey}','{$privateKey}',$time)";
        $bool = Db::execute($sql);    #数据插入数据库
        if(!$bool){
            throw new \LogicException('操作失败',1010);
        }
    }
    return $publicKey;
}
 
/**
 * 客户端获取公钥
 * 根据传递过来的设备号生成或者提取公钥
 * @return \think\response\Json
 */
public function sendKey(){
    if(request()->isPost()){
        $post = input('param.');
        $rsa = new Rsa();
        try{
            // 验证参数
            if(!isset($post['equipment'])){
                throw new \LogicException('参数错误',1020);
            }
            $result = $rsa->generateKey($post['equipment']);
        } catch (\Exception $e){
            return json_encode($e->getCode(),$e->getMessage());
        }
        return json_encode($result);
    }
}

| 客户端生成加密串格式

客户端自行根据rsa加密格式加密。这里将要加密的参数转成了json格式,并且对加密结果进行base_64加密,最后将以这种格式加密好的数据作为参数值进行传递。

比如:post传递的参数为equipment(设备号)和token,其中token需要进行加密,加密参数的key为encrypt。

客户端传递的参数则为:equipment:739CDF48-5318-415B-8228-CB6DCEBE777B,encrypt:{'token':522b04cbb0c5b56e5669b8ed56b43d88},其中encrypt参数值需要base_64加密。

/**
 * 数据加密
 * @param $publicKey
 * @param $data
 * @return string
 */
public function encrypt($publicKey,$data){
    openssl_public_encrypt(json_encode($data), $encrypted, $publicKey);
    return base64_encode($encrypted);
}

| 服务器端解密

服务器端需要接收客户端传来的设备号和加密参数,并且根据设备号来获取私钥解密。

/**
 * 数据解密
 * @param string $equipment
 * @param json string $encrypt
 * @throws \Exception
 * @return array $decrypted
 */
public function decrypt($equipment,$encrypt){
    $sql = "select `{$this->_config['RSA_PRIVATE_KEY']}` from `{$this->_config['RSA_TABLE']}` where `{$this->_config['RSA_UNIQUE']}` = {$equipment} limit 1";
    $privateKey = Db::query($sql);
    if(!$privateKey){
        throw new \LogicException('获取私钥失败',1004);
    }
    openssl_private_decrypt(base64_decode($encrypt), $decrypted, $privateKey); #私钥解密
    if(!$decrypted){
        throw new \LogicException('解密失败',1005);
    }
    return (array)json_decode($decrypted);
}

这样就拿到解密参数了,我比较习惯转成数组操作。不喜欢的自己换。拿到解密过的数据就可以啦。

|  版权声明:本文为博主原创文章,转载请注明出处。