zoukankan      html  css  js  c++  java
  • 关于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-----
    ".$pubKey."
    -----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-----
    ".$pubKey."
    -----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,如果你开心的话,你也可以写死。。。

    技术最菜,头发最少
  • 相关阅读:
    学习笔记-JMeter 操作 Mysql
    学习笔记-JMeter 关联
    学习笔记-JMeter参数化
    研究 Table DOM对象的属性和方法
    tornado web.py Application类源码剖析
    根据 HTTP header 收集客户端相关信息
    【指针】基于双向链表的list
    【指针】基于单向链表的list(待改进)
    【递归】汉诺塔
    【递归】全排列
  • 原文地址:https://www.cnblogs.com/gushengyan/p/9253127.html
Copyright © 2011-2022 走看看