双钥加密了解与应用:
公匙和私匙
采用RSA算法对网络数据进行加密传输,采用这种加密方式需要两串密匙,公开的叫公匙,没有公开的就叫私匙,公匙和私匙都可以用来加密解密文件,私匙加密的文件公匙解密同理公匙加密的文件可以用私匙来解密。公匙和私匙是同时存在的一对密匙
在本质上没有啥区别,只是统称人人都知道的就叫做公匙,只有自己知道的叫做私匙,这种公私的叫法其实是根据使用习惯来人为赋予的。
关于双钥加密适用于支付的对接
它可以保证信息的来源可靠性和信息的完整性。双钥加密就是生成两套密匙。例:A(私)a(公),B(私)b(公),此时甲拿着Ab,乙拿着aB,此时甲与乙通信,甲把内容使用A加密发送给乙,乙使用a解密内容;乙回复甲,乙使用B对内容加密发送给甲,甲使用b对内容解密。
图例
php关于RSA应用
生成
- 确定openssl.cnf时候存在
例如windows下
'e:/wnmp/php8.1.12/extras/ssl/openssl.cnf'
- 生成公匙私匙
基础配置
public $config = [
'config' => 'e:/wnmp/php8.1.12/extras/ssl/openssl.cnf',
//指定使用多少位 来生成密匙
'private_key_bits' => 2048,
//创建CSR是使用那些扩展
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
/**
* @param $path
* 保存路径
* @param $expire
* 保存天数
* @param $pass_phrase
* 密匙密码
*/
public function __construct($path = null, $expire = 365, $pass_phrase = 'xyytime')
{
$this->path = $path;
$this->expire = $expire;
$this->pass_phrase = $pass_phrase;
$this->time = time();
}
- 生成公匙私匙
/**
* 生成公匙密匙
* @return false|int
*/
public function generate()
{
//生成公匙私匙资源
$res = openssl_pkey_new($this->config);
//将key当做PEM编码字符串导出并保存到$this->private_key中
openssl_pkey_export($res, $this->private_key, $this->pass_phrase, $this->config);
//返回密匙详情数组(位长度,密匙,类型)
$pubKey = openssl_pkey_get_details($res);
//将私匙写入文件中
$keyPrivate = file_put_contents(app_path() . "{$this->path}/certs/{$this->time}_private.pem", $this->private_key);
//将公匙写入文件中
$keyPublic = file_put_contents(app_path() . "{$this->path}/certs/{$this->time}_public.pem", $pubKey["key"]);
//判断是否写入成功
if ($keyPrivate && $keyPublic) {
$result = $this->time;
return $result;
}
return false;
}
应用
<?php
namespace app\common\lib\rsa;
use think\Exception;
class Rsa
{
//私匙
private $_privKey;
//公匙
private $_pubKey;
//密匙保存路径
private $_KeyPath;
public function __construct($path)
{
if (empty($path) || !is_dir($path)) {
throw new Exception('没有传入密匙地址参数');
}
$this->_KeyPath = $path;
//设置私匙
$file = $this->_KeyPath . DIRECTORY_SEPARATOR . '1671549083_private.pem';
//将文件读取到字符串,读取私匙
$prk = file_get_contents($file);
//获取私匙,成功返回真实的密匙资源标识符,失败返回false
$this->_privKey = openssl_pkey_get_private($prk,'xyytime');
//设置公匙
$file = $this->_KeyPath . DIRECTORY_SEPARATOR . '1671549111_public.pem';
//将文件读取到字符串,读取公匙
$puk = file_get_contents($file);
//获取公匙,成功返回真实的密匙资源标识符,失败返回false
$this->_pubKey = openssl_pkey_get_public($puk);
}
/**
* 私匙加密
* @param $data
* @return string|null
*/
public function privEncrypt($data)
{
if (!is_string($data)) {
return null;
}
//使用私匙加密数据,成功返回true,失败返回false,$data要加密的数据,$encrypted_data加密后的数据,$this->_privKey私匙。
$str = openssl_private_encrypt($data, $encrypted_data, $this->_privKey);
if ($str) {
return base64_encode($encrypted_data);
}
return null;
}
/**
* 私匙解密
* @param $data
* @return mixed|null
*/
public function privDecrypt($data)
{
if (!is_string($data)) {
return null;
}
//使用私匙解密数据,成功返回true失败返回false;$data需要解密的数据,$decrypted_data解密后的数据,$this->_privKey这个key必须是和用来加密数据所用公匙对应的私匙
$str = openssl_private_decrypt($data, $decrypted_data, $this->_privKey);
if ($str) {
return $decrypted_data;
}
return null;
}
/**
* 公匙加密
* @param $data
* @return false|string|null
*/
public function pubEncrypt($data)
{
if (!is_string($data)) {
return null;
}
//使用公匙加密数据,成功返回true失败返回false;$data需要加密的数据,$encrypted_data加密后的数据,$thi->_pubKey公匙
$str = openssl_public_encrypt($data, $encrypted_data, $this->_pubKey);
if ($str) {
return json_encode($encrypted_data);
}
return null;
}
/**
* 公匙解密
* @param $data
* @return mixed|null
*/
public function pubDecrypt($data)
{
if (!is_string($data)) {
return null;
}
//使用公匙解密数据成功返回true失败返回false;$data需要解密的数据,$decrypted_data解密后的数据,$this->_pubKey,key同理key必须是和用来加密数据的私匙配对的公匙
$str = openssl_public_decrypt(base64_decode($data), $decrypted_data, $this->_pubKey);
if ($str) {
return $decrypted_data;
}
return null;
}
}
关于加密
- 对于要加密的数据要严格按照密匙说生成的位数来约定长度,如果字符串长度太长超过密匙位数约定长度,则会失败并报告长度超过限制
//指定使用多少位 来生成密匙
'private_key_bits' => 2048,
- 错误提示
//函数返回openSSL错误消息,成功返回错误信息字符串,如果没有错误信息返回false
openssl_error_string()