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;
**********************
那么该类会在初始化的时候检测公钥/私钥文件是否存在 若不存在则采用重新生成的方式生成
这个时候我们就可以实现每天/固定时间更新公钥/私钥确保更安全的数据传输
上一篇: 1.1 安全机制
下一篇: AES 对称加密 (JDK)