php Rsa签名算法
一:加签验签
class RsaController extends Controller{ /** * RSA签名 * @param $data 待签名数据 * @param $private_key 私钥字符串 * return 签名结果 */ public function rsaSign($data, $private_key) { // $search = [ // "-----BEGIN RSA PRIVATE KEY-----", // "-----END RSA PRIVATE KEY-----", // "\n", // "\r", // "\r\n" // ]; // $private_key=str_replace($search,"",$private_key); // $private_key=$search[0] . PHP_EOL . wordwrap($private_key, 64, "\n", true) . PHP_EOL . $search[1]; $res=openssl_get_privatekey($private_key); if($res) { openssl_sign($data, $sign,$res); openssl_free_key($res); }else { exit("私钥格式有误"); } $sign = base64_encode($sign); return $sign; } /** * RSA验签 * @param $data 待签名数据 * @param $public_key 公钥字符串 * @param $sign 要校对的的签名结果 * return 验证结果 */ public function rsaCheck($data, $public_key, $sign) { // $search = [ // "-----BEGIN PUBLIC KEY-----", // "-----END PUBLIC KEY-----", // "\n", // "\r", // "\r\n" // ]; // $public_key=str_replace($search,"",$public_key); // $public_key=$search[0] . PHP_EOL . wordwrap($public_key, 64, "\n", true) . PHP_EOL . $search[1]; $res=openssl_get_publickey($public_key); if($res) { $result = (bool)openssl_verify($data, base64_decode($sign), $res); openssl_free_key($res); }else{ exit("公钥格式有误!"); } return $result; } }
二:加签验签
$data为加签数据
Rsa SHA256 加签:
//Rsa SHA256 $priKey = file_get_contents(__DIR__.'/file.pem'); $privKeyId = openssl_pkey_get_private($priKey); $signature = ''; $algo = "SHA256"; openssl_sign($data, $signature, $privKeyId, $algo); openssl_free_key($privKeyId); $bs = base64_encode($signature);
Rsa SHA1 or Rsa 加签:
//Rsa SHA1 or Rsa $priKey = file_get_contents(__DIR__.'/file.pem'); $privKeyId = openssl_pkey_get_private($priKey); $signature = ''; openssl_sign($data, $signature, $privKeyId); openssl_free_key($privKeyId); $bs = base64_encode($signature);
$r = curl($url, "POST", $data, $bs);
验签:
/** *验签 * @param $data 待验签数据 * @param $sign 签名字符串(之前签名生成的$bs) * @param $pubKey 公钥字符串 * @return bool */ $pubKey = file_get_contents(__DIR__.'/pub.key'); //读取公钥 $pKey = checkSign($pubKey,$sign ,$data); function checkSign($pubKey,$sign,$toSign){ $publicKeyId = openssl_pkey_get_public($pubKey); $result = openssl_verify($toSign, base64_decode($sign), $publicKeyId); openssl_free_key($publicKeyId); return $result === 1 ? true : false; }
三:加密解密,解决长度超出返回false问题
$encrypt_data = encrypt($data,$public_key); $decrypt_data = decrypt($encrypt_data,$private_key); // 公钥加密数据 function encrypt($originalData,$pubkey){ $crypto = ''; foreach (str_split($originalData, 117) as $chunk) { openssl_public_encrypt($chunk, $encryptData, $pubkey); $crypto .= $encryptData; } return base64_encode($crypto); } // 公钥解密数据 function decrypt($encryptData,$privkey){ $crypto = ''; foreach (str_split(base64_decode($encryptData), 128) as $chunk) { openssl_private_decrypt($chunk, $decryptData, $privkey); $crypto .= $decryptData; } return $crypto; }
四: thinkphp公钥加密,私钥解密
<?php namespace app\admin\controller\functions; use app\admin\model\AdminLog; use app\common\controller\Backend; use think\Config; use think\Hook; use think\Validate; use app\admin\library\Auth; use Exception; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Reader\Xlsx; use PhpOffice\PhpSpreadsheet\Reader\Xls; use PhpOffice\PhpSpreadsheet\Reader\Csv; use think\Db; use think\exception\PDOException; use think\exception\ValidateException; /** * 后台首页 * @internal */ class Functions extends Backend { // 公钥文件 private $pubkey_file = ROOT_PATH."public". DS ."rsakey" . DS . 'pubKey.pem'; // 私钥文件 private $prikey_file = ROOT_PATH."public". DS ."rsakey" . DS . 'priKey.pem'; /** * RSA 公钥加密 */ public function pubEncrypt($data){ $pubkey = file_get_contents($this->pubkey_file); if(!$pubkey){ return ['code'=>0,'msg'=>"公钥不存在"]; } if (!is_string($data)) { return ['code'=>0,'msg'=>"加密字符串格式错误"]; } $r = openssl_public_encrypt($data, $encrypted, $pubkey); if ($r) { return base64_encode($encrypted); } return ['code'=>0,'msg'=>"加密失败"]; } /** * RSA 私钥解密 */ public function priDecrypt($encrypted){ $prikey = file_get_contents($this->prikey_file); if(!$prikey){ return ['code'=>0,'msg'=>"私钥不存在"]; } if (!is_string($encrypted)) { return ['code'=>0,'msg'=>"解密字符串格式错误"]; } $encrypted = base64_decode($encrypted); $r = openssl_private_decrypt($encrypted, $decrypted, $prikey); if ($r) { return $decrypted; } return ['code'=>0,'msg'=>"解密失败"]; } }
五:openssl_pkey_get_public返回false问题,如果一直返回false,不要用feil_get_contents取值,用'file://'.文件路径, (但是这里要注意的是,文件路径和 file:// 是两个部分)
$path = ROOT_PATH."public". DS ."key" . DS . 'pub.pem'; $this->_pubKey = openssl_pkey_get_public('file://'.$path);
-------------------------------------------