RSA接口加密实现方法

搞了一天,搜了好多资料,终于把公司接口RSA加密完成了,下面写一下完成的过程以及碰到的坑。

 $config = array(
     "config" => "C:/wamp64/bin/php/php5.6.16/extras/ssl/openssl.cnf",
     "digest_alg" => "sha512",
     "private_key_bits" => 1024,
     "private_key_type" => OPENSSL_KEYTYPE_RSA,
 );
// Create the private and public key
$res = openssl_pkey_new($config);

// Extract the private key from $res to $privKey
openssl_pkey_export($res, $privKey, NULL, $config);
echo "Private Key: ".$privKey. '
'; // Extract the public key from $res to $pubKey $pubKey = openssl_pkey_get_details($res); $pubKey = $pubKey["key"]; echo "Public Key: ".$pubKey. '
'; $data = 'token=coucou&tel=17600104539&url=https://www.coucouchina.com/Api/Index/manage?id=2'; echo "Data: ".$data. '
'; // Encrypt the data to $encrypted using the public key openssl_public_encrypt($data, $encrypted, $pubKey); $encrypted = base64_encode($encrypted); echo "Encrypted: ".$encrypted. '
'; // Decrypt the data using the private key and store the results in $decrypted $encrypted = base64_decode($encrypted); openssl_private_decrypt($encrypted, $decrypted, $privKey); echo "Decrypted: ".$decrypted. '
';
RSA接口加密实现方法_第1张图片
image.png

一:首先用上面的代码生成private key和public key
坑①:$config数组里面的路径不要填错
坑②:第15行的 $config 不要忘记填

二:在项目里面建立 rsa_public_key.pem 和 rsa_private_key.pem两个文件,把上一步生成的private key 和 public key 填入对应的文件之中
坑①:格式正确一定要,该换行换行,不然下面会死得很难看

class RSA  {  
    private $pubKey = null;  
    private $priKey = null;  
  
    /** 
     * 构造函数 
     * 
     * @param string 公钥文件(验签和加密时传入) 
     * @param string 私钥文件(签名和解密时传入) 
     */  
    public function __construct($public_key_file = '', $private_key_file = '')  
    {  
        if ($public_key_file) {  
            $this->_getPublicKey($public_key_file);  
        }  
        if ($private_key_file) {  
            $this->_getPrivateKey($private_key_file);  
        }  
    }  
  
    // 私有方法  
    /** 
     * 自定义错误处理 
     */  
    private function _error($msg)  
    {  
        die('RSA Error:' . $msg); //TODO
    }  
  
    /** 
     * 检测填充类型 
     * 加密只支持PKCS1_PADDING 
     * 解密支持PKCS1_PADDING和NO_PADDING 
     * 
     * @param int 填充模式 
     * @param string 加密en/解密de 
     * @return bool 
     */  
    private function _checkPadding($padding, $type)  
    {  
        if ($type == 'en') {  
            switch ($padding) {  
                case OPENSSL_PKCS1_PADDING:  
                    $ret = true;  
                    break;  
                default:  
                    $ret = false;  
            }  
        } else {  
            switch ($padding) {  
                case OPENSSL_PKCS1_PADDING:  
                case OPENSSL_NO_PADDING:  
                    $ret = true;  
                    break;  
                default:  
                    $ret = false;  
            }  
        }  
        return $ret;  
    }  
  
    private function _encode($data, $code)  
    {  
        switch (strtolower($code)) {  
            case 'base64':  
                $data = base64_encode('' . $data);  
                break;  
            case 'hex':  
                $data = bin2hex($data);  
                break;  
            case 'bin':  
            default:  
        }  
        return $data;  
    }  
  
    private function _decode($data, $code)  
    {  
        switch (strtolower($code)) {  
            case 'base64':  
                $data = base64_decode($data);  
                break;  
            case 'hex':  
                $data = $this->_hex2bin($data);  
                break;  
            case 'bin':  
            default:  
        }  
        return $data;  
    }  
  
    private function _getPublicKey($file)  
    {  
        $key_content = $this->_readFile($file);  
        if ($key_content) {  
            $this->pubKey = openssl_get_publickey($key_content);  
        }  
    }  
  
    private function _getPrivateKey($file)  
    {  
        $key_content = $this->_readFile($file);  
        if ($key_content) {  
            $this->priKey = openssl_get_privatekey($key_content);               //格式问题会导致返回数据为false
        } 
    }  
  
    private function _readFile($file)  
    {  
        $ret = false;  
        if (!file_exists($file)) {  
            $this->_error("The file {$file} is not exists");  
        } else {  
            $ret = file_get_contents($file);  
        }  
        return $ret;  
    }  
  
    private function _hex2bin($hex = false)  
    {  
        $ret = $hex !== false && preg_match('/^[0-9a-fA-F]+$/i', $hex) ? pack("H*", $hex) : false;  
        return $ret;  
    }  
  
    /** 
     * 生成签名 
     * 
     * @param string 签名材料 
     * @param string 签名编码(base64/hex/bin) 
     * @return 签名值 
     */  
    public function sign($data, $code = 'base64')  
    {  
        $ret = false;  
        if (openssl_sign($data, $ret, $this->priKey)) {  
            $ret = $this->_encode($ret, $code);  
        }  
        return $ret;  
    }  
  
    /** 
     * 验证签名 
     * 
     * @param string 签名材料 
     * @param string 签名值 
     * @param string 签名编码(base64/hex/bin) 
     * @return bool 
     */  
    public function verify($data, $sign, $code = 'base64')  
    {  
        $ret = false;  
        $sign = $this->_decode($sign, $code);  
        if ($sign !== false) {  
            switch (openssl_verify($data, $sign, $this->pubKey)) {  
                case 1:  
                    $ret = true;  
                    break;  
                case 0:  
                case -1:  
                default:  
                    $ret = false;  
            }  
        }  
        return $ret;  
    }  
  
    /** 
     * 加密 
     * 
     * @param string 明文 
     * @param string 密文编码(base64/hex/bin) 
     * @param int 填充方式(貌似php有bug,所以目前仅支持OPENSSL_PKCS1_PADDING) 
     * @return string 密文 
     */  
    public function encrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING)  
    {  
        $ret = false;  
        if (!$this->_checkPadding($padding, 'en')) $this->_error('padding error');  
        if (openssl_public_encrypt($data, $result, $this->pubKey, $padding)) {  
            $ret = $this->_encode($result, $code);  
        }  
        return $ret;  
    }  
  
    /** 
     * 解密 
     * 
     * @param string 密文 
     * @param string 密文编码(base64/hex/bin) 
     * @param int 填充方式(OPENSSL_PKCS1_PADDING / OPENSSL_NO_PADDING) 
     * @param bool 是否翻转明文(When passing Microsoft CryptoAPI-generated RSA cyphertext, revert the bytes in the block) 
     * @return string 明文 
     */  
    public function decrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING, $rev = false)  
    {  
        $ret = false;  
        $data = $this->_decode($data, $code);  
        if (!$this->_checkPadding($padding, 'de')) $this->_error('padding error');  
        if ($data !== false) {  
            if (openssl_private_decrypt($data, $result, $this->priKey, $padding)) {  
                $ret = $rev ? rtrim(strrev($result), "\0") : '' . $result;  
            }  
        }  
        return $ret;  
    }  
}  

![image.png](http://upload-images.jianshu.io/upload_images/421014-53cf0fc3cc0692da.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![image.png](http://upload-images.jianshu.io/upload_images/421014-ceee292f9b07eadb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![image.png](http://upload-images.jianshu.io/upload_images/421014-761740c02d2a831d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![image.png](http://upload-images.jianshu.io/upload_images/421014-72141a3bdae8fba2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![image.png](http://upload-images.jianshu.io/upload_images/421014-e931ab21165cab59.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

$pubfile = 'C:\wamp64\www\coucou\rsa_public_key.pem';  
$prifile = 'C:\wamp64\www\coucou\rsa_private_key.pem';  
$rsa = new RSA($pubfile, $prifile);  
$rst = array(  
    'ret' => 200,  
    'code' => 1,  
    'data' => array(1, 2, 3, 4, 5, 6),  
    'msg' => "success",  
);  
$ex = json_encode($rst);  
//加密  
$ret_e = $rsa->encrypt($ex);  
//解密  
$ret_d = $rsa->decrypt($ret_e);  
echo $ret_e;
echo '
';
echo $ret_d;
  
echo '
';  
  
$a = 'test';  
//签名  
$x = $rsa->sign($a);  
//验证  
$y = $rsa->verify($a, $x);  
var_dump($x, $y);  
exit;  
RSA接口加密实现方法_第2张图片
image.png

三:这些代码主要用作加密和解密
坑①:第149行一定要注意
坑②:第255行跟256行的路径一定要对

ok,完成,YEAH!!

你可能感兴趣的:(RSA接口加密实现方法)