Open diffnest opened 7 years ago
在对接玖富债权项目中,用到了RSA加解密算法,特此记录下;
公私钥成对出现,相互解密; 公钥加密,私钥解密。 私钥数字签名,公钥验证。
生成RSA秘钥对,主要利用linux OPENSSL
2.1 生成RSA私钥 genrsa -out rsa_private_key.pem 1024
genrsa -out rsa_private_key.pem 1024
2.2 把RSA私钥转换成PKCS8格式 pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
2.3 生成RSA公钥 rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
打开rsa_public_key.pem可以看到-----BEGIN PUBLIC KEY-----开头, -----END PUBLIC KEY-----结尾的没有换行的字符串,这个就是公钥
PHP中实现加解密类
class RSA { private $pubKey = null; private $priKey = null; /** * 构造函数 * @param string 公钥文件(验签和加密时传入) * @param string 私钥文件(签名和解密时传入) */ public function __construct($pubKeyFile = '', $priKeyFile = '') { if ($pubKeyFile) { $this->pubKey = $this->getFileContent($pubKeyFile); } if ($priKeyFile) { $this->priKey = $this->getFileContent($priKeyFile); } } /** * RSA签名 * @param $data 待签名数据 * @param $priKey 商户私钥文件路径 或 密钥内容本身 * return $sign 签名结果 */ public function sign($data, $code = 'base64') { $result = openssl_get_privatekey($this->priKey); if (openssl_sign($data, $sign, $result)) { openssl_free_key($result); $sign = $this->encode($sign, $code); } return $sign; } /** * 验证签名 * @param $data 待签名数据 * @param $sign 要校对的的签名结果 * @param string 签名编码(base64/hex/bin) * @return bool */ public function verify($data, $sign, $code = 'base64') { $ret = false; $result = openssl_get_publickey($this->pubKey); $sign = $this->decode($sign, $code); if ($sign !== false) { $ret = (bool) openssl_verify($data, $sign, $result); openssl_free_key($result); } return $ret; } /** * RSA加密 * @param $content 需要加密的内容 * @param $this->pubKey 商户公钥文件路径 或 密钥内容本身 * return 加密后内容,明文 */ public function encrypt($content, $code = 'base64') { $result = openssl_get_publickey($this->pubKey); $rslt = ''; for ($i = 0; $i < ((strlen($content)-strlen($content)%117) / 117 + 1); $i++) { $data = mb_strcut($content, $i * 117, 117, 'utf-8'); openssl_public_encrypt($data, $encrypted, $result); $rslt .= $encrypted; } openssl_free_key($result); $rslt = $this->encode($rslt, $code); return $rslt; } /** * RSA解密 * @param $content 需要解密的内容,密文 * @param $this->priKey 商户私钥文件路径 或 密钥内容本身 * return 解密后内容,明文 */ public function decrypt($content, $code = 'base64') { $result = openssl_get_privatekey($this->priKey); $content = $this->decode($content, $code); $rslt = ''; for ($i = 0; $i < strlen($content)/128; $i++) { $data = substr($content, $i * 128, 128); openssl_private_decrypt($data, $decrypt, $result); $rslt .= $decrypt; } openssl_free_key($result); return $rslt; } private function encode($data, $code) { switch (strtolower($code)) { case 'base64': $data = base64_encode(''.$data); break; } return $data; } private function decode($data, $code) { switch (strtolower($code)) { case 'base64': $data = base64_decode($data); break; } return $data; } private function getFileContent($file) { if (file_exists($file)) { return file_get_contents($file); } return $file; } }
4.代码中具体调用:
/** * 同步债权信息 * @param $orderNo 订单ID * @param $memberId 玖富理财用户ID * @return boolen */ function syncRepayPlan($sDate, $eDate) { if (!$sDate || !$eDate) { return false; } $data = array('inputCharset' => jiufuStatus::JIUFU_INPUTCHARSET, 'version' => jiufuStatus::JIUFU_VERSION, 'channelId' => jiufuStatus::JIUFU_CHANNELID, 'startTime' => $sDate, 'endTime' => $eDate, ); $requestNo = sprintf("%d:'%s':'%s'", jiufuStatus::REQTYPE_JIUFU_RSYNC_REPAY_PLAN, 'jiufuSyncRepayPlan', uniqid()); $dataString = json_encode($data); $info = array( 'requestno' => $requestNo, 'type' => jiufuStatus::REQTYPE_JIUFU_RSYNC_REPAY_PLAN, 'reqtime' => CMI_DATE_NOW, 'data' => $dataString ); $r = $this->xdReqst->createRequest($requestNo, jiufuStatus::REQTYPE_JIUFU_RSYNC_REPAY_PLAN, $info); if ($r) { $rslt = $this->excuteReq(__FUNCTION__, $data); return $this->handleRepayPlan($requestNo, $rslt); } } /** * 处理还款计划 * @param $requestNo 请求ID * @param $rslt * @return boolen */ function handleRepayPlan($requestNo, $rslt) { if ($rslt['returnCode'] != '0000' || empty($rslt['responseData'])) { printf('获取还款计划失败%s', $rslt['returnMessage']); return false; } $dataList = $rslt['responseData']; foreach ($dataList as $key => &$value) { $value['channelId'] = $rslt['channelId']; } $classFun = __FUNCTION__; $handleObj = new handleData(); $handleObj->valList = $dataList; $r = $handleObj->$classFun(); if ($r['Status'] == 'Fail') { $error = $r['Message']; $this->xdReqst->updateRequest($requestNo, REQSTATUS_FAILED, array('data' => $data, 'errorMsg' => $error)); $this->errorMsg(__LINE__. $error); return false; } $this->xdReqst->updateRequest($requestNo, REQSTATUS_SUCCESS, $r); return true; } /** * 发送请求 * @param $reqName 请求名称 * @param $data 请求数据 * @return array */ public function excuteReq($reqName, $data = null) { $rsaObj = new rsa(PUBLIC_KEY_PATH, PRIVATE_KEY_PATH); //加密加签 $secretData = $rsaObj->encrypt(json_encode($data)); $secretSign = $rsaObj->sign(base64_decode($secretData)); //请求接口 $rslt = $this->proxy->$reqName(array('data' => $secretData, 'sign' => $secretSign)); if (!$rsaObj->verify(base64_decode($rslt['data']), $rslt['sign'])) { $error = sprintf("验签失败"); $this->errorMsg(__LINE__. $error); } //解密接口返回数据 $rsltData = $rsaObj->decrypt($rslt['data']); return json_decode($rsltData, true); }
公私钥成对出现,相互解密; 公钥加密,私钥解密。 私钥数字签名,公钥验证。
生成RSA秘钥对,主要利用linux OPENSSL
2.1 生成RSA私钥
genrsa -out rsa_private_key.pem 1024
2.2 把RSA私钥转换成PKCS8格式
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
2.3 生成RSA公钥
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
PHP中实现加解密类
4.代码中具体调用: