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;
    }    
}
View Code

二:加签验签

$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);
View Code

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);
View Code

$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;
    }
View Code

 三:加密解密,解决长度超出返回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;
}
View Code

 四: 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'=>"解密失败"];
        

    } 
    
    

}
View Code

五: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);
View Code

 

 

 

 

 

-------------------------------------------

 

posted on 2019-03-08 22:49  逝年-  阅读(1244)  评论(0编辑  收藏  举报