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. '<br />';
// Extract the public key from $res to $pubKey
$pubKey = openssl_pkey_get_details($res);
$pubKey = $pubKey["key"];
echo "Public Key: ".$pubKey. '<br />';
$data = 'token=coucou&tel=17600104539&url=https://www.coucouchina.com/Api/Index/manage?id=2';
echo "Data: ".$data. '<br />';
// Encrypt the data to $encrypted using the public key
openssl_public_encrypt($data, $encrypted, $pubKey);
$encrypted = base64_encode($encrypted);
echo "Encrypted: ".$encrypted. '<br />';
// 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. '<br />';
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 '<pre>';
echo $ret_d;
  
echo '<pre>';  
  
$a = 'test';  
//签名  
$x = $rsa->sign($a);  
//验证  
$y = $rsa->verify($a, $x);  
var_dump($x, $y);  
exit;  
image.png

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

ok,完成,YEAH!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容

  • /**ios常见的几种加密方法: 普通的加密方法是讲密码进行加密后保存到用户偏好设置( [NSUserDefaul...
    彬至睢阳阅读 2,834评论 0 7
  • 嘟哝嘟哝:最近接到一个任务:在客户端动态生成RSA密钥对,然后向服务器发送这个密钥对中的公钥字符串,由服务器进行公...
    TimmyR阅读 7,862评论 19 21