访客地图

PHP AES和RSA加密类实现与示例

张成
2016/3

<?php
/**
 * Created by PhpStorm.
 * User: zc
 * Date: 2016/3/12
 * Time: 13:35
 */
/**
 * Class Base64
 *       MIME base64 编码数据辅助类 兼顾URL传输
 */
class Base64
{
    public static function base64EncodeForUrl($data)
    {
        $str = base64_encode($data);
        return strtr($str, '+/=', '-_!');
    }
    public static function base64DecodeForUrl($data)
    {
        $str = strtr($data, '-_!','+/=');
        return base64_decode($str);
    }
}
/**
 * Class AES
 *  AES加密类
 *
 */
class AES
{
    //加密私钥 32位
    var $private_key = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
    //初始化向量 16位
    var $iv = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    /**
     * 加密
     *       使用CBC模式 会使用IV 加密强度比ECB模式好
     * @param $data
     *
     * @return string
     */
    function encryptToken($data)
    {
        $padding = 16 - (strlen($data) % 16);
        //填充补齐长度 为 16的倍数
        $data .= str_repeat(chr($padding), $padding);
        return Base64::base64EncodeForUrl(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->private_key, $data, MCRYPT_MODE_CBC, $this->iv));
    }
    /**
     * 解密
     * @param $data
     *
     * @return string
     */
    function decryptToken($data)
    {
        $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->private_key, Base64::base64DecodeForUrl($data), MCRYPT_MODE_CBC, $this->iv);
        $padding = ord($data[strlen($data) - 1]);
        return substr($data, 0, -$padding);
    }
}
/**
 * Class RSA
 *
 *
 *  linux系统生成公私钥对方法:
 *
 * openssl genrsa -out rsa_private_key.pem 1024
 * openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem
 * openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
 * 第一条命令生成原始 RSA私钥文件 rsa_private_key.pem,
 * 第二条命令将原始 RSA私钥转换为 pkcs8格式,
 * 第三条生成RSA公钥 rsa_public_key.pem
 *
 */
abstract class RSA
{
    public $private_key;
    public $public_key;
    public $private_resource;
    public $public_resource;
    function __construct($private_key = '',$public_key = '')
    {
        if(!extension_loaded('openssl'))
        {
            throw new Exception('openssl does not loaded!'.PHP_EOL);
        }
        $this->private_key = $private_key;
        $this->public_key = $public_key;
        $this->init();
    }
    public function init(){}
    abstract function encode($source);
    abstract function decode($encrypted);
    /**
     *  发签名的使用私钥
     *
     * @param $data 待签名的数据
     *
     * @return string
     */
    public function sign($data){
        if($this->private_resource == null){
            return '';
        }
        openssl_sign($data,$sign,$this->private_resource);
        return $sign;
    }
    /**
     * 验证签名的使用对方公开的公钥
     *
     * @param $data  待签名的数据
     * @param $signData 签名
     *
     * @return bool
     */
    public function verifySign($data,$signData)
    {
        echo $data.PHP_EOL;
        echo $signData.PHP_EOL;
        if($this->public_resource == null){
            return 0;
        }
        return openssl_verify($data,$signData,$this->public_resource);
    }
}
/**
 * Class RSAClient
 *      RSA加密解密 客户端类
 */
class RSAClient extends RSA
{
    public function init()
    {
        $this->private_resource = openssl_pkey_get_private($this->private_key);
        if($this->private_resource === false){
            throw new Exception('private_resource does not support for RSAServer !'.PHP_EOL);
        }
        $this->public_resource = openssl_pkey_get_public($this->public_key);
        if($this->public_resource === false){
            throw new Exception('public_key does not support for RSAClient !'.PHP_EOL);
        }
    }
    function encode($source)
    {
        $flag = openssl_public_encrypt($source,$encrypted,$this->public_resource);
        if($flag){
            return Base64::base64EncodeForUrl($encrypted);
        }else{
            return false;
        }
    }
    function decode($encrypted)
    {
        $encrypted = Base64::base64DecodeForUrl($encrypted);
        $flag = openssl_public_encrypt($encrypted,$decrypted,$this->public_resource);
        if($flag){
            return $decrypted;
        }else{
            return false;
        }
    }
}
/**
 * Class RSAServer
 *      RSA加密解密服务端类
 */
class RSAServer extends RSA
{
    public function init()
    {
        $this->private_resource = openssl_pkey_get_private($this->private_key);
        if($this->private_resource === false){
            throw new Exception('private_resource does not support for RSAServer !'.PHP_EOL);
        }
        $this->public_resource = openssl_pkey_get_public($this->public_key);
        if($this->public_resource === false){
            throw new Exception('public_key does not support for RSAClient !'.PHP_EOL);
        }
    }
    /**
     * 服务器端加密 用私钥加密
     * @param $source
     *
     * @return mixed
     */
    function encode($source)
    {
        $flag = openssl_private_encrypt($source,$encrypted,$this->private_resource);//私钥加密
        if($flag){
            return Base64::base64EncodeForUrl($encrypted);
        }else{
            return false;
        }
    }
    /**
     * 服务器端解密 用私钥解密
     * @param $encrypted
     *
     * @return mixed
     */
    function decode($encrypted)
    {
        $encrypted = Base64::base64DecodeForUrl($encrypted);
        $flag = openssl_private_decrypt($encrypted,$decrypted,$this->private_resource);
        if($flag){
            return $decrypted;
        }else{
            return false;
        }
    }
}
//客户端私钥和公钥
//私钥
$client_private_key = '-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC3//sR2tXw0wrC2DySx8vNGlqt3Y7ldU9+LBLI6e1KS5lfc5jl
TGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2klBd6h4wrbbHA2XE1sq21ykja/
Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o2n1vP1D+tD3amHsK7QIDAQAB
AoGBAKH14bMitESqD4PYwODWmy7rrrvyFPEnJJTECLjvKB7IkrVxVDkp1XiJnGKH
2h5syHQ5qslPSGYJ1M/XkDnGINwaLVHVD3BoKKgKg1bZn7ao5pXT+herqxaVwWs6
ga63yVSIC8jcODxiuvxJnUMQRLaqoF6aUb/2VWc2T5MDmxLhAkEA3pwGpvXgLiWL
3h7QLYZLrLrbFRuRN4CYl4UYaAKokkAvZly04Glle8ycgOc2DzL4eiL4l/+x/gaq
deJU/cHLRQJBANOZY0mEoVkwhU4bScSdnfM6usQowYBEwHYYh/OTv1a3SqcCE1f+
qbAclCqeNiHajCcDmgYJ53LfIgyv0wCS54kCQAXaPkaHclRkQlAdqUV5IWYyJ25f
oiq+Y8SgCCs73qixrU1YpJy9yKA/meG9smsl4Oh9IOIGI+zUygh9YdSmEq0CQQC2
4G3IP2G3lNDRdZIm5NZ7PfnmyRabxk/UgVUWdk47IwTZHFkdhxKfC8QepUhBsAHL
QjifGXY4eJKUBm3FpDGJAkAFwUxYssiJjvrHwnHFbg0rFkvvY63OSmnRxiL4X6EY
yI9lblCsyfpl25l7l5zmJrAHn45zAiOoBrWqpM5edu7c
-----END RSA PRIVATE KEY-----';
//公钥
$client_public_key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3//sR2tXw0wrC2DySx8vNGlqt
3Y7ldU9+LBLI6e1KS5lfc5jlTGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2kl
Bd6h4wrbbHA2XE1sq21ykja/Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o
2n1vP1D+tD3amHsK7QIDAQAB
-----END PUBLIC KEY-----';
//服务端私钥和公钥
$server_pubkey ='-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3//sR2tXw0wrC2DySx8vNGlqt
3Y7ldU9+LBLI6e1KS5lfc5jlTGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2kl
Bd6h4wrbbHA2XE1sq21ykja/Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o
2n1vP1D+tD3amHsK7QIDAQAB
-----END PUBLIC KEY-----';;
$server_prikey ='-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC3//sR2tXw0wrC2DySx8vNGlqt3Y7ldU9+LBLI6e1KS5lfc5jl
TGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2klBd6h4wrbbHA2XE1sq21ykja/
Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o2n1vP1D+tD3amHsK7QIDAQAB
AoGBAKH14bMitESqD4PYwODWmy7rrrvyFPEnJJTECLjvKB7IkrVxVDkp1XiJnGKH
2h5syHQ5qslPSGYJ1M/XkDnGINwaLVHVD3BoKKgKg1bZn7ao5pXT+herqxaVwWs6
ga63yVSIC8jcODxiuvxJnUMQRLaqoF6aUb/2VWc2T5MDmxLhAkEA3pwGpvXgLiWL
3h7QLYZLrLrbFRuRN4CYl4UYaAKokkAvZly04Glle8ycgOc2DzL4eiL4l/+x/gaq
deJU/cHLRQJBANOZY0mEoVkwhU4bScSdnfM6usQowYBEwHYYh/OTv1a3SqcCE1f+
qbAclCqeNiHajCcDmgYJ53LfIgyv0wCS54kCQAXaPkaHclRkQlAdqUV5IWYyJ25f
oiq+Y8SgCCs73qixrU1YpJy9yKA/meG9smsl4Oh9IOIGI+zUygh9YdSmEq0CQQC2
4G3IP2G3lNDRdZIm5NZ7PfnmyRabxk/UgVUWdk47IwTZHFkdhxKfC8QepUhBsAHL
QjifGXY4eJKUBm3FpDGJAkAFwUxYssiJjvrHwnHFbg0rFkvvY63OSmnRxiL4X6EY
yI9lblCsyfpl25l7l5zmJrAHn45zAiOoBrWqpM5edu7c
-----END RSA PRIVATE KEY-----';
$a = new AES();
$cli = new RSAClient($client_private_key,$server_pubkey);
$ser = new RSAServer($server_prikey,$client_public_key);
$param['key'] = $cli->encode($a->private_key);
$param['sign'] = Base64::base64EncodeForUrl($cli->sign($param['key']));//签名
$param['data'] = $a->encryptToken('zhangcheng');
var_dump($param);
$dkey = $ser->decode($param['key']);
echo $ser->decode($param['key']);//使用RSA服务端解密 AES的私钥  校验AES私钥
echo PHP_EOL;
echo $a->decryptToken($param['data']);//使用AES解密正文数据
echo PHP_EOL;
//校验
var_dump( $ser->verifySign($param['key'] , Base64::base64DecodeForUrl($param['sign'])) );