欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PHP 非对称加密实现

程序员文章站 2022-05-15 16:59:55
...

PHP 实现非对称加密逻辑 -实现保护用户数据安全

在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明文加密成复杂的密文。目前主流加密手段大致可分为单向加密和双向加密。

单向加密:通过对数据进行摘要计算生成密文,密文不可逆推还原。算法代表:Base64,MD5,SHA; 

双向加密:与单向加密相反,可以把密文逆推还原成明文,双向加密又分为对称加密和非对称加密。

对称加密:指数据使用者必须拥有相同的**才可以进行加密解密,就像彼此约定的一串暗号。算法代表:DES,3DES,AES,IDEA,RC4,RC5;

非对称加密:相对对称加密而言,无需拥有同一组**,非对称加密是一种“信息公开的**交换协议”。非对称加密需要公开**和私有**两组**,公开**和私有**是配对起来的,
也就是说使用公开**进行数据加密,只有对应的私有**才能解密。这两个**是数学相关,用某用户**加密后的密文,只能使用该用户的加***才能解密。如果知道了其中一个,并
不能计算出另外一个。因此如果公开了一对**中的一个,并不会危害到另外一个**性质。这里把公开的**为公钥,不公开的**为私钥。算法代表:RSA,DSA。

非对称加密算法

需要两个**:公开**(publickey)和私有**(privatekey)。
公开**与私有**是一对,如果用公开**对数据进行加密,只有用对应的私有**才能解密;
如果用私有**对数据进行加密,那么只有用对应的公开**才能解密。
因为加密和解密使用的是两个不同的**,所以这种算法叫作非对称加密算法。

注意以上的一个点,公钥加密的数据,只有对应的私钥才能解密

在日常使用中是酱紫的:

将私钥private_key.pem用在服务器端,公钥发放给android跟ios等前端

客户端用公钥加密过后,数据只能被拥有唯一私钥的服务器看懂。

代码:

<?php
namespace Classes\Third\Utils;


/**
 * 非对称加密
 * @author	田小涛
 * @date	2019年10月30日
 * @comment 数据安全机制
 *
 */
class RsaUtils
{
    
    //公钥
    private $private;
    //私钥
    private $public;
    //公-私钥存储位置
    private $keyPath;
    private $openssl;
    
    private static $_instance;
    private function __construct()
    {
        $this->keyPath = dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'rsa';
        $this->openssl = 'D:\Works\phpStudy\PHPTutorial\Apache\conf\openssl.cnf';
        $this->_init();
    }
    public static function getInstance()
    {
        if( null == self::$_instance )
        {
            self::$_instance = new self();
        }
        
        return self::$_instance;
    }
    
    /**
     * 初始化公-私钥
     * @author	 田小涛
     * @datetime 2019年10月30日 下午1:14:01
     * @comment	
     * 
     * @return boolean
     */
    private function _init()
    {
        if( !file_exists( $this->keyPath . DIRECTORY_SEPARATOR . 'private_key.pem'  ) || !file_exists( $this->keyPath . DIRECTORY_SEPARATOR . 'public_key.pem' ) )
        {
            $this->initialization();
        }
        
        return true;
    }
    
    /**
     * 初始化公-私钥
     * @author	 田小涛
     * @datetime 2019年10月30日 下午1:05:59
     * @comment	
     *
     */
    protected function initialization()
    {
        $config = array(
            'digest_alg'        => 'sha512',
            'private_key_bits'  => 2048,
            'private_key_type'  => OPENSSL_KEYTYPE_RSA,
            'config'            => $this->openssl,
        );
        try{
            //创建**对
            $res = openssl_pkey_new( $config );
            //生成私钥
            openssl_pkey_export($res, $privkey, null, $config);
            //生成公钥
            $pubKey = openssl_pkey_get_details($res)[ 'key' ];
            file_put_contents( $this->keyPath . DIRECTORY_SEPARATOR . 'private_key.pem', $privkey );
            file_put_contents( $this->keyPath . DIRECTORY_SEPARATOR . 'public_key.pem', $pubKey );
            
            $this->private = openssl_pkey_get_private( $privkey );
            $this->public = openssl_pkey_get_public( $privkey );
        }catch ( \Exception $e ){
            
        }
        
        return true;
    }
    
    
    /**
     * 提取私钥
     * @author	 田小涛
     * @datetime 2019年10月30日 上午11:38:02
     * @comment	
     * 
     * @return resource
     */
    private function _getPrivateKey()
    {
        $strPrivateKey = $this->keyPath . DIRECTORY_SEPARATOR. 'private_key.pem';
        $key = file_get_contents( $strPrivateKey );
        
        return openssl_pkey_get_private( $key );
    }
    
    
    /**
     * 提取公钥
     * @author	 田小涛
     * @datetime 2019年10月30日 上午11:38:15
     * @comment	
     * 
     * @return resource
     */
    private function _getPublicKey()
    {
        $strPublicKey = $this->keyPath . DIRECTORY_SEPARATOR . 'public_key.pem';
        $key = file_get_contents( $strPublicKey );
        
        return openssl_pkey_get_public( $key );     
    }
    
    
    /**
     * 获取公钥
     * @author	 田小涛
     * @datetime 2019年10月30日 上午11:41:31
     * @comment	
     * 
     * @return resource
     */
    public function getPublicKey()
    {
        $this->public =  $this->_getPublicKey();
        
        return $this->public;
    }
    
    /**
     * 获取私钥
     * @author	 田小涛
     * @datetime 2019年10月30日 上午11:41:53
     * @comment	
     * 
     * @return resource
     */
    public function getPrivateKey()
    {
        $this->private =  $this->_getPrivateKey();
        
        return $this->private;
    }
    
    
    /**
     * 私钥加密
     * @author	 田小涛
     * @datetime 2019年10月30日 上午11:43:42
     * @comment	
     * 
     * @param unknown $data
     */
    public function privEncrypt( $data = null )
    {
        if( is_null( $data ) )
        {
            return null;
        }
        if ( ( is_array( $data ) || is_object( $data ) ) && !empty( $data ) ) 
        {
            $data = json_encode( $data );
        }
        
        return openssl_private_encrypt( $data, $encrypted, $this->_getPrivateKey() ) ? base64_encode( $encrypted ) : null; 
    }
    
    /**
     * 公钥加密
     * @author	 田小涛
     * @datetime 2019年10月30日 上午11:43:42
     * @comment	
     * 
     * @param unknown $data
     */
    public function publicEncrypt( $data = null )
    {
        if( is_null( $data ) )
        {
            return null;
        }
        if ( ( is_array( $data ) || is_object( $data ) ) && !empty( $data ) ) 
        {
            $data = json_encode( $data );
        }   
        
        return openssl_public_encrypt( $data, $encrypted, $this->_getPublicKey() ) ? base64_encode( $encrypted ) : null; 
    }
    
    
    /**
     * 私钥解密
     * @author	 田小涛
     * @datetime 2019年10月30日 上午11:47:50
     * @comment	
     * 
     * @param unknown $encrypted
     */
    public function privDecrypt( $encrypted = null )
    {
        if( is_null( $encrypted ) || !is_string( $encrypted ) || strlen( $encrypted ) <= 0 )
        {
            return null;
        }
        
        return ( openssl_private_decrypt( base64_decode( $encrypted ), $decrypted, $this->_getPrivateKey() ) ) ? $decrypted : null;    
    }
    
    /**
     * 公钥解密
     * @author	 田小涛
     * @datetime 2019年10月30日 上午11:47:50
     * @comment	
     * 
     * @param unknown $encrypted
     */
    public function publicDecrypt( $encrypted = null )
    {
        if( is_null( $encrypted ) || !is_string( $encrypted ) || strlen( $encrypted ) <= 0 )
        {
            return null;
        }
        
        return ( openssl_public_decrypt( base64_decode( $encrypted ), $decrypted, $this->_getPublicKey() ) ) ? $decrypted : null;    
    }
    
    
}

调用示例:

$en  = RsaUtils::getInstance();
$data = [ 'id' => 1, 'name' => '张三', 'age' => 12 ];
echo '<pre>';
var_dump( $data );
echo '<pre>';
$encrypt = $en->publicEncrypt( $data );
echo '加密字符串:' . $encrypt . '<br />';
$de = $en->privDecrypt( $encrypt );
    
echo '<pre>';
var_dump( json_decode( $de, true )  );
echo '<pre>';
exit;

PHP 非对称加密实现

**********************

那么该类会在初始化的时候检测公钥/私钥文件是否存在 若不存在则采用重新生成的方式生成

这个时候我们就可以实现每天/固定时间更新公钥/私钥确保更安全的数据传输