关于RSA加密跟AES加密

前几天跟某三大运营商之一的机构合作做了个页面,申请了联调接口,不得不说大公司真的是....(形容词自行脑补吧),要个现成的接口走流程都走了两三天。

说到这个加密,又是AES又是RSA,真的好不复杂。

代码贴出来,免得自己又忘记。

首先是AES加密,作为对称性加密。key的话16位或者24位唯一随机字符串就可以了。接口方用得16位,所以我在用32位的时候出现了解密失败。于是demo也用32位的。

AES的类:(接口方放用的是AES/ECB/PKCS5Padding,所以我这里用OPENSSL_PKCS1_PADDING,可以互通,原因不明)

class AES{

    public static function encrypt($data, $key) {
        return base64_encode(openssl_encrypt($data, 'aes-128-ecb', $key, OPENSSL_PKCS1_PADDING));//OPENSSL_PKCS1_PADDING 不知道为什么可以与PKCS5通用,未深究
    }

    public static function decrypt($data, $key) {
        return openssl_decrypt(base64_decode($data), 'aes-128-ecb', $key, OPENSSL_PKCS1_PADDING);//OPENSSL_PKCS1_PADDING 不知道为什么可以与PKCS5通用,未深究
    }

}

使用代码:

    public function msgkey($data){
        $aes          = substr(md5(time()),0,16);//16位aes密钥
        $rsa          =  new RSA();
        $info         =  Db::name('info')->where('id=1')->find();
        $public_key   =  $info['public_key'];
        $aesKey       = $rsa->rsaEncrypt($aes,$public_key);//接口方公钥加密aes密钥

        if($data!=''){
            $m          = new AES();
            $aesKeyData = $m->encrypt($data, $aes);
            return $aesKeyData;
        }else{
            return $aesKey;
        }
    }

在这一步的时候还遇到了一些问题,就是data传进去的时候有值,但是出来的时候就空了,emmmmm。。。原因忘记了,反正后来是改好了。这个方法是因为那边的接口需要AES加密传送的数据,然后AES密钥又要用RSA加密。。。那么接下来

RSA加密:非对称加密 双方互换公钥保留私钥,网上有很多帮助理解非对称加密的小故事,简单来讲,就是我给你买了个芒果快递给你,快递给你之前呢,我用你给我买的口红(口红是你给我的公钥)在上面画了个爱心,然后签了个名字(Sign),你拿到之后,看到是个画了爱心的芒果,然后你用自己跟口红一起买的,自己偷偷留下的专用卸妆纸(你的私钥)擦了下,掉了,然后你看到了真的芒果,那你怎么判断这个芒果就是我给你寄的呢,你看到了我的sign,验证了一下,嗯,确实是我给你寄的,你就放心的吃了。(大概是这个意思吧)

RSA类:(因为对方没有给我证书文件,所以我直接把对方的公钥跟自己的私钥都存在数据库的)

class RSA
{
    /**
     * RSA签名
     * @param $data 待签名数据
     * @param $private_key_path 商户私钥文件路径
     * return 签名结果
     */
    function rsaSign($data) {
        $info= Db::name('info')->where('id=1')->find();
        $priKey = $info['my_prikey'];
//        $priKey = file_get_contents($private_key_path);
        $res = openssl_get_privatekey($priKey);
        openssl_sign($data, $sign, $res,OPENSSL_ALGO_SHA256 );
        openssl_free_key($res);
        //base64编码
        $sign = base64_encode($sign);
        return $sign;
    }

    /**
     * RSA验签
     * @param $data 待签名数据
     * @param $ali_public_key_path 支付宝的公钥文件路径
     * @param $sign 要校对的的签名结果
     * return 验证结果
     */


    function rsaVerify($data, $sign)  {
        $data=strtoupper(md5($data));
        $info= Db::name('info')->where('id=1')->find();
        $pubKey = $info['hsh_public_key'];
        $res = openssl_get_publickey("-----BEGIN PUBLIC KEY-----\n".$pubKey."\n-----END PUBLIC KEY-----");
        $result = (bool)openssl_verify($data, base64_decode($sign), $res,OPENSSL_ALGO_SHA256);
        openssl_free_key($res);
        return $result;
    }
    function rsaEncrypt($content){
        $info= Db::name('info')->where('id=1')->find();
        $pubKey = $info['hsh_public_key'];
        $res = openssl_get_publickey("-----BEGIN PUBLIC KEY-----\n".$pubKey."\n-----END PUBLIC KEY-----");
//        dump($res);exit;
        //把需要加密的内容,按128位拆开解密
        $result  = '';
        for($i = 0; $i < strlen($content)/128; $i++  ) {
            $data = substr($content, $i * 128, 128);
            openssl_public_encrypt ($data, $encrypt, $res);
            $result .= $encrypt;
        }
        $result = base64_encode($result);
        openssl_free_key($res);
        return $result;
    }
    /**
     * RSA解密
     * @param $content 需要解密的内容,密文
     * @param $private_key_path 商户私钥文件路径
     * return 解密后内容,明文
     */
    function rsaDecrypt($content) {
        $info= Db::name('info')->where('id=1')->find();
        $priKey = $info['my_prikey'];
        $res = openssl_get_privatekey($priKey);
        //用base64将内容还原成二进制
        $content = base64_decode($content);
        //把需要解密的内容,按128位拆开解密
        $result  = '';
        for($i = 0; $i < strlen($content)/128; $i++  ) {
            $data = substr($content, $i * 128, 128);
            openssl_private_decrypt($data, $decrypt, $res);
            $result .= $decrypt;
        }
        openssl_free_key($res);
        return $result;
    }
}

使用方法:

需要注意的是,公钥跟私钥的前后缀必须要有,不论是文件还是存在数据库,emmmmmm,如果你开心的话,你也可以写死。。。

猜你喜欢

转载自www.cnblogs.com/gushengyan/p/9253127.html