PHP非对称加密:RSA (RSA/ECB/PKCS1Padding)+base64_encode/bin2hex加密
生活随笔
收集整理的這篇文章主要介紹了
PHP非对称加密:RSA (RSA/ECB/PKCS1Padding)+base64_encode/bin2hex加密
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
所謂非對(duì)稱(chēng),就是使用公鑰/私鑰加密,然后用對(duì)應(yīng)的私鑰/公鑰解密
?1.配對(duì)的公鑰,私鑰:
//公鑰(注意包括頭(-----BEGIN PUBLIC KEY-----)尾(-----END PUBLIC KEY-----)標(biāo)志) -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbdq5NjtUEkAQ6wucPuhC0aRvSMsaX3GrhkwsLLdWZnVNVpkJRw yPFq9HJNuntRw7P9Sb3TkwrpN60x62kZ6qV8h1GoG4jIfofuVWPv1VzudAV6kWJWMl3sc +DtV5q1dy1KQLb6e90cuOynzxVT3j+Fx7ZOzovmdTkEcoRiYWV1QIDAQAB -----END PUBLIC KEY-----//私鑰(注意包括頭(-----BEGIN RSA PRIVATE KEY-----)尾(-----END RSA PRIVATE KEY-----)標(biāo)志) -----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擴(kuò)展是否安裝
extension_loaded('openssl') or die('PHP加密需要openssl擴(kuò)展支持');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類(lèi)型的密鑰,如果密鑰文件內(nèi)容被破壞,openssl_pkey_get_private函數(shù)返回false */ $privateKey = openssl_pkey_get_private($this->privateKey);/** * 生成Resource類(lèi)型的公鑰,如果公鑰文件內(nèi)容被破壞,openssl_pkey_get_public函數(shù)返回false */ $publicKey = openssl_pkey_get_public($this->publicKey);($privateKey) or die('密鑰不可用'); ($publicKey) or die('公鑰不可用');4.公鑰加密
由于openssl_public_encrypt()加密對(duì)加密串有字符限制(117字節(jié)),所有需要分段加密(每段32個(gè)字符,加密后拼接起來(lái))
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()加密對(duì)加密串有字符限制(128字節(jié)),所有需要分段解密后拼接起來(lái)
// 私鑰解密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();//正式環(huán)境$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;}//檢測(cè)密鑰+加密public function rsa_pass($params, $api_method, $is_big){extension_loaded('openssl') or die('php需要openssl擴(kuò)展支持');/*** 生成Resource類(lèi)型的密鑰,如果密鑰文件內(nèi)容被破壞,openssl_pkey_get_private函數(shù)返回false*/$privateKey = openssl_pkey_get_private($this->privateKey);/*** 生成Resource類(lèi)型的公鑰,如果公鑰文件內(nèi)容被破壞,openssl_pkey_get_public函數(shù)返回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, '錯(cuò)誤報(bào)文:');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, '錯(cuò)誤報(bào)文:');echo json_encode($param_back, JSON_UNESCAPED_UNICODE);exit;}/*** 原數(shù)據(jù)*/$originalData = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); // var_dump(strlen($originalData));die;//用公鑰加密$encryptData = $this->encryptedByPublicKey($originalData);return $encryptData;}/*** 簽名 + post請(qǐng)求* @param array $params 請(qǐng)求參數(shù)* @param string $method 第三方方法名* @param string $api_method 接口名* @param string $is_big 通道別名* @param string $bankcardNo 銀行卡號(hào)* @return mixed*/public function sign_post($params, $method, $api_method, $is_big, $bankcardNo = ''){$this->log($params, $api_method, $is_big, '業(yè)務(wù)數(shù)據(jù):', $bankcardNo);//公鑰加密(RSA/ECB/PKCS1Padding)$encryptData = $this->rsa_pass($params, $api_method, $is_big);$merSign = "merIdNum=" . $this->merIdNum . "&encryptData=" . $encryptData . "&merKey=" . $this->merKey;//公共參數(shù)$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, '請(qǐng)求url:');$this->log($request_param, $api_method, $is_big, '請(qǐng)求報(bào)文:');$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, '響應(yīng)報(bào)文:');// $third_array = [ // 'userStatus'=>'E0000', // 'userMsg'=>'綁卡申請(qǐng)成功', // 'encryptData'=>'lVa1eNpFP5V6ImaFbk2s2mu7ptY8cHc+ANrI3o38ZTdeR+OfZsOA1BeWD8vDacBl7eFA7GgTA6OM2mzIuwlT4wkgm8IpNshRwtKHwTAri0c4HsZ+2qTfZJjybiB36eJ3CsiPntlae7wsMcNx9hxlDvcs19D77mufEVhTWYQYcHc=', // 'merIdNum'=>'dc0020450', // 'merSign'=>'79d52ca53003c3c7b73916dac313c38a', // ]; // $this->log($third_array, $api_method, $is_big, '響應(yīng)報(bào)文:');$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, '解密報(bào)文:');//處理返回$third_array['data'] = json_decode($third_res);//解密報(bào)文:{"orderDesc":"交易成功","orderStatus":"SUCCESS","userLinkId":"YCDA9CA_257919_162701706280078"}} else {//失敗響應(yīng)的兩種情況//【2021-07-22 15:56:23】響應(yīng)報(bào)文:{"userStatus":"E0000","userMsg":"結(jié)算請(qǐng)求已受理","encryptData":"Rfyvdj3HUOtGzMAbP4Jh4EQpd9VXDr7BLQD5fRwz+TOvCwI6EubNv4MdXCWuRN1zm9C17bvt27jx1I67ceVHhFW/vpqNEBG5eTmqJjXP6PJrJwiyf03yrK3EUOXf7wgpdAH5NW3PrywrWLmt/lC2hNvUf02iQ0gXRxN3Ka6X9k4a1QfjSJRXYTXdUlVshDWx+Y1gMKRvLTrOW4IzaJpyYpd/KXI7ahEAYqWCqEruPhRIUV9N+z+lECHIeG0Ml/sC7/AdBTs4oT+LgMNGsxCH5n1RoFj4EhqcVCrrrYW5O900sdrn78xURWo3yvkL2up6vDMV9fmViV2udwAVC+wD6Q==","merIdNum":"dc0020663","merSign":"342e58237f3e68213f23815410585a9b"}//【2021-07-22 15:56:23】解密報(bào)文:{"orderDesc":"商戶手續(xù)費(fèi)金額超過(guò)了最大手續(xù)費(fèi)限制","orderStatus":"FAIL","userLinkId":"YCDA9CA_162990_162694058243001"}//------------------------//【2021-07-23 11:01:03】響應(yīng)報(bào)文:{"userStatus":"E0002","userMsg":"用戶余額不足"}//這樣處理了之后前端才不會(huì)出錯(cuò) $third_array['data'] = ["orderDesc" => $third_array['userMsg'],"orderStatus" => "FAIL",//訂單狀態(tài) SUCCESS 交易成功 FAIL交易失敗 PROCESSING 交易處理中];}$third_json = json_encode($third_array, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);return $third_json;}//接口post請(qǐng)求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); //超時(shí)時(shí)間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 /內(nèi)容* @param $method /方法名* @param $bankcardNo /銀行卡號(hào)* @param string $is_big /通道別名* @param string $title /標(biāo)題*/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)) { //判斷目錄是否存在 不存在就創(chuàng)建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);} }對(duì)應(yīng)的私鑰加密和公鑰加密函數(shù)
openssl_private_encrypt($data,$encrypted,$this->privateKey);//私鑰加密
openssl_public_decrypt($encrypted,$decrypted,$this->publicKey);//私鑰加密的內(nèi)容通過(guò)公鑰可用解密出來(lái)
?參考博文:https://blog.csdn.net/qq_27517377/article/details/79047021
總結(jié)
以上是生活随笔為你收集整理的PHP非对称加密:RSA (RSA/ECB/PKCS1Padding)+base64_encode/bin2hex加密的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 锂电池洗车机能用软包电池吗?
- 下一篇: PHP类的自动加载