RSA数字证书公钥密钥生成:
在Linux系统下运行一下命令生成:
如果提示输出密码,可以为空
生成的公钥rsa_public_key.pem和密钥rsa_private_key.pem文件在根目录下
# openssl# genrsa -out rsa_private_key.pem 2048 Generating RSA private key, 2048 bit long modulus# pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt# rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
签名算法sha256withrsa:
$string:需要加密的字符串
$binary_signature:加密后保存到该变量中
$this->privateKey:RSA的私钥。(使用file_get_contents()可获取);
openssl_sign($string, $binary_signature, $this->privateKey, OPENSSL_ALGO_SHA256);
实例:
签名算法使用sha256withrsa算法,我方和渠道伙伴需交换RSA数字证书公钥用于验证签名,签名时,使用RSA数字证书私钥对签名参数串进行签名,RSA密用2048位及以上的,将签名值使用BASE64转码后填充到报文的数字签名域(Signature)。验证签名时,使用对方颁发的RSA数字证书公钥进行验签
/*** 签名 + post请求* @param array $param 请求参数* @param string $method 第三方方法名* @param string $api_method 接口名* @param string $is_big 通道别名* @param int $phone 手机号码* @return mixed*/public function sign_post($param, $method, $api_method, $is_big, $phone){$param['reqTime'] = date('YmdHis');$param['partnerId'] = $this->partnerId;$this->log($param, $api_method, $is_big, '签名前数据:', $phone);$signature = $this->makeSign($param);$this->log($signature, $api_method, $is_big, '签名值:');$param['signature'] = $signature;$types = explode('_',$api_method);if($types[0] == 'sk'){$requestUrl = $this->edUrl . $method;}else{$requestUrl = $this->zdUrl . $method;}$this->log($requestUrl, $api_method, $is_big, '请求url:');$this->log($param, $api_method, $is_big, '请求报文:');$res = $this->curl($requestUrl, $param);$this->log($res, $api_method, $is_big, '响应报文:');return $res;}/*** 生成签名* @param $params array 请求参数* @param $privateKey string 秘钥* @return $sign string 签名内容*/public function makeSign($params){//签名步骤一:按字典序排序参数,再把所有数组值以“&”字符连接起来ksort($params);$string = $this->toUrlParams($params);openssl_sign($string, $binary_signature, $this->privateKey, OPENSSL_ALGO_SHA256);$sign = base64_encode($binary_signature);return $sign;}/*** 格式化参数格式化成url参数* @param $params array*/public function toUrlParams($params){$buff = "";foreach ($params as $k => $v) {if ($v != "" && !is_array($v)) {$buff .= $k . "=" . $v . "&";}}$buff = trim($buff, "&");return $buff;}//接口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);$output = curl_exec($ch);curl_close($ch);return $output;}/*** 验签* @param $data array 需要验签的数据*/public function verifySign($data, $publicKey){if (empty($data) || empty($data['signature'])) {return false;}$sign = $data['signature'];unset($data['signature']);ksort($data);$string = $this->ToUrlParams($data);$pubKey = "-----BEGIN PUBLIC KEY-----\n" .wordwrap($publicKey, 64, "\n", true) ."\n-----END PUBLIC KEY-----";$result = (bool)openssl_verify($string, base64_decode($sign), $pubKey, OPENSSL_ALGO_SHA256);return $result;}/*** 日志记录* @param $data /内容* @param $method /方法名* @param $phone /手机号* @param string $is_big /通道别名* @param string $title /标题*/public function Log($data, $method, $is_big, $title, $phone = ''){$str = is_array($data) ? json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : $data;if (empty($phone)) {$content = '【' . date('Y-m-d H:i:s') . '】' . $title . $str . PHP_EOL;} else {$content = ' phone:' . $phone . '【' . 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);}