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非对称加密:RSA (RSA/ECB/PKCS1Padding)+base64_encode/bin2hex加密相关推荐
- Go语言的DES加密(CBC模式, ECB模式) ---- 与java加密互通(转)
问题场景: 业务需要对接接口, 采用DES加密方式加密, 于是google一下go的DES加密方式, go的DES的默认隐藏了ECB模式, 因为go认为ECB不安全, 所以不建议使用,就隐藏了, 然而 ...
- rsa/ecb/pkcs1padding php,PHPJAVA RSA/ECB/PKCS1Padding 加密解密
PHP代码: $privateKeyFilePath = '-----BEGIN RSA PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwgg ...
- python rsa加密长度_python RSA加密最新(RSA/ECB/PKCS1Padding)
遇到一个 java 的RSA/ECB/PKCS1Padding 加密 要改成python的 网上搜一堆不靠谱的,没办法只能自己动手写一份了 中间遇到一个ERROR: OverflowError: 45 ...
- 非对称加密之RSA算法
非对称加密之RSA算法 1. RSA算法简述 2. 模型分析 3.代码实现 3.1 算法实现 3.2 测试代码 3.3 测试结果 4. 算法实现分析 5. 数据分段处理 该系列文章列表 1.网络及数据 ...
- Python代码实现MD5、AES对称加密和RSA非对称加密以及OpenSSl实践
1.MD5加密算法 1.1 MD5加密的特点 不可逆运算 对不同的数据加密的结果是定长的32位和16位字符(不管文件多大都一样) 对相同的数据加密,得到的结果是一样的(也就是复制). 抗修改性 :信息 ...
- [crypto]-52-python3中rsa(签名验签加密解密)aes(ecb cbc ctr)hmac的使用,以及unittest测试用
环境: 在ubuntu14.04下,记得安装:sudo pip3 install pycrypto 代码示例1: =========================== import base64 f ...
- 对称加密、非对称加密、RSA、消息摘要、数字签名、数字证书与 HTTPS 简介
文章目录 1.加密算法简介 1.1 对称加密(Symmetric Key Algorithms) 1.2 非对称加密(Asymmetric Key Algorithms) 1.3 非对称加密 RSA ...
- 非对称加密下RSA在Java的简明教程
引言 在现实世界中,每个人都有自己的密码.在各种系统中都有各类加密和解密的需求. 本文将详细介绍一下RSA的前身后世,应用场景和在Java中的实现,从理论到实践,一步到位,触手可用. 非对称加密与对称 ...
- 非对称算法之一RSA加密解密的java demo
RSA加密算法,著名的非对称加密算法之一. 1,私钥加密,公钥解密例子(通常用在数字证书签名上). package rsa;import org.apache.commons.codec.binary ...
最新文章
- 基于单片机的超市储物柜设计_657【毕设课设】基于单片机智能存柜储物柜存储柜系统设计...
- 基因组序列及注释数据下载
- (转)iOS开发资源:推送通知相关开源项目--PushSharp、APNS-PHP以及Pyapns等
- golang中的http conn实现分析
- Javascript----input事件实现动态监听textarea内容变化
- EJB3.0 Timer
- python新手入门代码-新手必看:手把手教你入门 Python
- [解决]RESTEASY003215: could not find writer for content-type text/html type: java.lang.String
- 信号与系统学习难点(一)群时延与相频特性
- Linux环境下利用perl脚本批量筛选VCF文件指定样本
- SpringBoot从入门到精通教程(三十)- 支付宝企业支付集成(五分钟集成)
- python数学公式识别_python用re正则表达式实现数学公式计算
- Cocos Creator 获得手机陀螺仪(Gyrometer)数据
- 如何单步调试存储过程
- mysql导出数据到文件
- 快手,存在的优势都有哪些???
- 灵魂拷问!Mysql和Redis数据同步该怎么做?请查收
- 怎么最快地复制一张表?
- Gitee+PicGo上传图片失败404 - {“status“:“404“,“error“:“Not Found“}
- 智能电视 屏幕测试软件,详解如何使用液晶电视测试软件
热门文章
- malloc,colloc,realloc内存分配,动态库,静态库的生成与调用
- MULE ESB功能介绍
- html text width,HTML5 Text Canvas rotate in case text width is larger than maximum width allowed
- NodeJs 在window中安装使用
- 目标检测中召回率(Recall),精确率(Precision),平均正确率(Average_precision(AP) ),交除并(Intersection-over-Union(IoU))
- Dropout_layer.cpp(防止过拟合)
- 补码(为什么按位取反再加一):告诉你一个其实很简单的问题
- 基于Walle的多渠道快速打包自动脚本
- Java之控制反转和依赖注入
- 2016及以后的自动化测试趋势 -《测试技术六月刊》