IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> PHP非对称加密:RSA (RSA/ECB/PKCS1Padding)+base64_encode/bin2hex加密 -> 正文阅读

[PHP知识库]PHP非对称加密:RSA (RSA/ECB/PKCS1Padding)+base64_encode/bin2hex加密

所谓非对称,就是使用公钥/私钥加密,然后用对应的私钥/公钥解密

?1.配对的公钥,私钥:

//公钥(注意包括头(-----BEGIN PUBLIC KEY-----)尾(-----END PUBLIC KEY-----)标志)
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbdq5NjtUEkAQ6wucPuhC0aRvSMsaX3GrhkwsLLdWZnVNVpkJRw
yPFq9HJNuntRw7P9Sb3TkwrpN60x62kZ6qV8h1GoG4jIfofuVWPv1VzudAV6kWJWMl3sc
+DtV5q1dy1KQLb6e90cuOynzxVT3j+Fx7ZOzovmdTkEcoRiYWV1QIDAQAB
-----END PUBLIC KEY-----


//私钥(注意包括头(-----BEGIN RSA PRIVATE KEY-----)尾(-----END RSA PRIVATE KEY-----)标志)
-----BEGIN RSA PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKBc0G8WmfydUuX6TnO5M3lSmNYqy8beEgBn24vWk6sWCZ2va+TRIWEew5dxmMXg5+N40a2XOJfyTxCALvzts+/J0q8efi2WIecPecWGNoDB8ZehGfzv3BQD5skk9sf1tL6ztU5tquPFajwmO85WR2pTFfk0CXgPEtLzPxntYfHpAgMBAAECgYB6DSo24qTgt3zYvOHpAhRDSrI4jun5uhtJY8Kdc/uAQ42eDl24EdOt75Q+N59nO/5CCzrLPEU+oJW8oVMh/mjr6gMv7QxhEr1iUrZmvAGTO2kB5sMgWfqPkiHeGddYWawcWGhAwQEJrrgGVldzaslY9FvWcmTjCjypEVvB7l1BgQJBAOJwB2RbRbI+z0d1M6DOawyu+J7JleMAQ42x9KyhiwYc/D0CZX0gkuyqGcwSh+c1CYjjdoRIh/531e1OZyBmRG0CQQC1TG68k+iXuz14+fgpHEttl2E3lQ6VfIzv+oaQHnRmmT92t2Eci70zkDFjVCGXxwQ279EokmP6RWfJG5Z1nV3tAkAZkHpVKzTQLeUq9SFyCzvsv6hUDQA+E56M1cWA4/AVLZqQrL+Wg+HylDW7Y3AyeztrV/rebm3kHdVqKEreTo11AkBPUou40nYXvQKeZbAgPJL79hnA+eSRnxcDAHfTop+HLFHKHV3N4Y38e4BAV1UDVT4Q00iOGc7Id4l7QijIePvZAkEA1OmJfbsaCx3T+4lZahzo8k7NzP5BS6izPVAVk8O3LHo3TggJZMa69Nc+8O82ZXOiOSt7bSONaST54ejjN8yhtg==
-----END RSA PRIVATE KEY-----

?2.判断openssl扩展是否安装

 extension_loaded('openssl') or die('PHP加密需要openssl扩展支持');

3.判断公钥和私钥是否可用?

//私钥文件路径   
$this->privateKey = file_get_contents(dirname(__FILE__) .'libraries/YCPAY/account/rsa_private_key.pem');

//公钥文件路径   
$this->publicKey = file_get_contents(dirname(__FILE__) . 'libraries/YCPAY/account/rsa_public_key.pem');  

/**
* 生成Resource类型的密钥,如果密钥文件内容被破坏,openssl_pkey_get_private函数返回false
*/
$privateKey = openssl_pkey_get_private($this->privateKey);


/**
* 生成Resource类型的公钥,如果公钥文件内容被破坏,openssl_pkey_get_public函数返回false
*/
$publicKey = openssl_pkey_get_public($this->publicKey);

($privateKey) or die('密钥不可用');
($publicKey) or die('公钥不可用');

4.公钥加密

由于openssl_public_encrypt()加密对加密串有字符限制(117字节),所有需要分段加密(每段32个字符,加密后拼接起来)

    define("BAOFOO_ENCRYPT_LEN", 32);    
    // 公钥加密
    function encryptedByPublicKey($data_content)
    {
        $publicKey = openssl_pkey_get_public($this->publicKey);
        $encrypted = "";
        $totalLen = strlen($data_content);
        $encryptPos = 0;
        while ($encryptPos < $totalLen) {
//            openssl_public_encrypt(substr($data_content, $encryptPos, BAOFOO_ENCRYPT_LEN), $encryptData, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
            openssl_public_encrypt(substr($data_content, $encryptPos, BAOFOO_ENCRYPT_LEN), $encryptData, $publicKey);
//            $encrypted .= bin2hex($encryptData);
            $encrypted .= base64_encode($encryptData);
            $encryptPos += BAOFOO_ENCRYPT_LEN;
        }
        return $encrypted;
    }

5.私钥解密

由于openssl_private_decrypt()加密对加密串有字符限制(128字节),所有需要分段解密后拼接起来

    // 私钥解密
    function encryptedByPrivateKey($data_content)
    {
        $privateKey = openssl_pkey_get_private($this->privateKey);

        $crypto = '';
        $data_content = base64_decode($data_content);
        foreach (str_split($data_content, 128) as $chunk) {
            openssl_private_decrypt($chunk, $decryptData, $privateKey);
            $crypto .= $decryptData;
        }
        return $crypto;
    }

?6.完整代码如下,仅供参考

define("BAOFOO_ENCRYPT_LEN", 32);

//CI框架
class YcPay extends MY_Controller
{
    private $privateKey;
    private $publicKey;
    private $merIdNum;
    private $merKey;
    private $url;

    public function __construct()
    {
        parent::__construct();

        //正式环境
        $this->privateKey = file_get_contents(APPPATH . 'libraries/YCPAY/account/rsa_private_key.pem');
        $this->publicKey = file_get_contents(APPPATH . 'libraries/YCPAY/account/rsa_public_key.pem');
        $this->merIdNum = 'dc0020663';
        $this->merKey = '5446042869aaf86d22c5d19189f21956';
        $this->url = 'https://mis.ixianhe.cn/action/exp/';
    }


    // 公钥加密
    function encryptedByPublicKey($data_content)
    {
//        $data_content = base64_encode($data_content);

        $publicKey = openssl_pkey_get_public($this->publicKey);
        $encrypted = "";
        $totalLen = strlen($data_content);
        $encryptPos = 0;
        while ($encryptPos < $totalLen) {
//            openssl_public_encrypt(substr($data_content, $encryptPos, BAOFOO_ENCRYPT_LEN), $encryptData, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
            openssl_public_encrypt(substr($data_content, $encryptPos, BAOFOO_ENCRYPT_LEN), $encryptData, $publicKey);
//            $encrypted .= bin2hex($encryptData);
            $encrypted .= base64_encode($encryptData);
            $encryptPos += BAOFOO_ENCRYPT_LEN;
        }
        return $encrypted;
    }

    // 私钥解密
    function encryptedByPrivateKey($data_content)
    {
        $privateKey = openssl_pkey_get_private($this->privateKey);

        $crypto = '';
        $data_content = base64_decode($data_content);
        foreach (str_split($data_content, 128) as $chunk) {
            openssl_private_decrypt($chunk, $decryptData, $privateKey);
            $crypto .= $decryptData;
        }
        return $crypto;
    }

    //检测密钥+加密
    public function rsa_pass($params, $api_method, $is_big)
    {
        extension_loaded('openssl') or die('php需要openssl扩展支持');

        /**
         * 生成Resource类型的密钥,如果密钥文件内容被破坏,openssl_pkey_get_private函数返回false
         */
        $privateKey = openssl_pkey_get_private($this->privateKey);
        /**
         * 生成Resource类型的公钥,如果公钥文件内容被破坏,openssl_pkey_get_public函数返回false
         */
        $publicKey = openssl_pkey_get_public($this->publicKey);
//        ($privateKey) or die('密钥不可用');
//        ($publicKey) or die('公钥不可用');
        if (empty($privateKey)) {
            $param_back = [
                'resCode' => '9999',
                'resMsg' => '密钥不可用',
            ];
            $this->log($param_back, 'rsa_pass', $is_big, '错误报文:');
            echo json_encode($param_back, JSON_UNESCAPED_UNICODE);
            exit;
        }
        if (empty($publicKey)) {
            $param_back = [
                'resCode' => '9999',
                'resMsg' => '公钥不可用',
            ];
            $this->log($param_back, $api_method, $is_big, '错误报文:');
            echo json_encode($param_back, JSON_UNESCAPED_UNICODE);
            exit;
        }


        /**
         * 原数据
         */
        $originalData = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
//        var_dump(strlen($originalData));die;


        //用公钥加密
        $encryptData = $this->encryptedByPublicKey($originalData);
        return $encryptData;
    }

    /**
     * 签名 + post请求
     * @param array $params 请求参数
     * @param string $method 第三方方法名
     * @param string $api_method 接口名
     * @param string $is_big 通道别名
     * @param string $bankcardNo 银行卡号
     * @return mixed
     */
    public function sign_post($params, $method, $api_method, $is_big, $bankcardNo = '')
    {
        $this->log($params, $api_method, $is_big, '业务数据:', $bankcardNo);

        //公钥加密(RSA/ECB/PKCS1Padding)
        $encryptData = $this->rsa_pass($params, $api_method, $is_big);

        $merSign = "merIdNum=" . $this->merIdNum . "&encryptData=" . $encryptData . "&merKey=" . $this->merKey;

        //公共参数
        $request_param = [
            'merVersion' => '3.0',
            'merIdNum' => $this->merIdNum,
            'requestMethod' => 'exp.' . $method,
            'merSign' => md5($merSign),
            'encryptData' => $encryptData,
        ];

        $requestUrl = $this->url . $method;
        $this->log($requestUrl, $api_method, $is_big, '请求url:');
        $this->log($request_param, $api_method, $is_big, '请求报文:');

        $request_param = json_encode($request_param, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $res = $this->curl($requestUrl, $request_param);
        $this->log($res, $api_method, $is_big, '响应报文:');

//        $third_array = [
//            'userStatus'=>'E0000',
//            'userMsg'=>'绑卡申请成功',
//            'encryptData'=>'lVa1eNpFP5V6ImaFbk2s2mu7ptY8cHc+ANrI3o38ZTdeR+OfZsOA1BeWD8vDacBl7eFA7GgTA6OM2mzIuwlT4wkgm8IpNshRwtKHwTAri0c4HsZ+2qTfZJjybiB36eJ3CsiPntlae7wsMcNx9hxlDvcs19D77mufEVhTWYQYcHc=',
//            'merIdNum'=>'dc0020450',
//            'merSign'=>'79d52ca53003c3c7b73916dac313c38a',
//        ];
//        $this->log($third_array, $api_method, $is_big, '响应报文:');

        $third_array = json_decode($res, true);
        if ($third_array['userStatus'] == 'E0000' && isset($third_array['encryptData'])) {
            //私钥解密
            $third_res = $this->encryptedByPrivateKey($third_array['encryptData']);
            $this->log($third_res, $api_method, $is_big, '解密报文:');

            //处理返回
            $third_array['data'] = json_decode($third_res);
            //解密报文:{"orderDesc":"交易成功","orderStatus":"SUCCESS","userLinkId":"YCDA9CA_257919_162701706280078"}
        } else {
            //失败响应的两种情况
            //【2021-07-22 15:56:23】响应报文:{"userStatus":"E0000","userMsg":"结算请求已受理","encryptData":"Rfyvdj3HUOtGzMAbP4Jh4EQpd9VXDr7BLQD5fRwz+TOvCwI6EubNv4MdXCWuRN1zm9C17bvt27jx1I67ceVHhFW/vpqNEBG5eTmqJjXP6PJrJwiyf03yrK3EUOXf7wgpdAH5NW3PrywrWLmt/lC2hNvUf02iQ0gXRxN3Ka6X9k4a1QfjSJRXYTXdUlVshDWx+Y1gMKRvLTrOW4IzaJpyYpd/KXI7ahEAYqWCqEruPhRIUV9N+z+lECHIeG0Ml/sC7/AdBTs4oT+LgMNGsxCH5n1RoFj4EhqcVCrrrYW5O900sdrn78xURWo3yvkL2up6vDMV9fmViV2udwAVC+wD6Q==","merIdNum":"dc0020663","merSign":"342e58237f3e68213f23815410585a9b"}
            //【2021-07-22 15:56:23】解密报文:{"orderDesc":"商户手续费金额超过了最大手续费限制","orderStatus":"FAIL","userLinkId":"YCDA9CA_162990_162694058243001"}
            //------------------------
            //【2021-07-23 11:01:03】响应报文:{"userStatus":"E0002","userMsg":"用户余额不足"}

            //这样处理了之后前端才不会出错 
            $third_array['data'] = [
                "orderDesc" => $third_array['userMsg'],
                "orderStatus" => "FAIL",//订单状态 SUCCESS 交易成功  FAIL交易失败  PROCESSING  交易处理中
            ];
            
        }
        $third_json = json_encode($third_array, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        return $third_json;
    }

    //接口post请求
    public function curl($url = '', $data = '')
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        if (!empty($data)) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //超时时间30秒
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $headers = [
            'Content-type: application/json'
        ];
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $output = curl_exec($ch);
        curl_close($ch);

        return $output;
    }

    /**
     * 日志记录
     * @param $data /内容
     * @param $method /方法名
     * @param $bankcardNo /银行卡号
     * @param string $is_big /通道别名
     * @param string $title /标题
     */
    public function Log($data, $method, $is_big, $title, $bankcardNo = '')
    {
        $str = is_array($data) ? json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : $data;
        if (empty($bankcardNo)) {
            $content = '【' . date('Y-m-d H:i:s') . '】' . $title . $str . PHP_EOL;
        } else {
            $content = ' bankcardNo:' . $bankcardNo . '【' . date('Y-m-d H:i:s') . '】' . $title . $str . PHP_EOL;
        }
        $path = APPPATH . "../PAYLOG/$is_big/$method/";

        if (!is_dir($path)) { //判断目录是否存在 不存在就创建
            mkdir($path, 0777, true);
        }
        file_put_contents($path . date("Y-m-d") . '.txt', $content, FILE_APPEND);
        //换行分割
        file_put_contents($path . date("Y-m-d") . '.txt', '------------------------' . PHP_EOL, FILE_APPEND);
    }
}

对应的私钥加密和公钥加密函数

openssl_private_encrypt($data,$encrypted,$this->privateKey);//私钥加密

openssl_public_decrypt($encrypted,$decrypted,$this->publicKey);//私钥加密的内容通过公钥可用解密出来

?参考博文:https://blog.csdn.net/qq_27517377/article/details/79047021

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:22:59  更:2021-07-31 16:23:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 15:15:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码