双钥加密了解与应用:

  1. 公匙和私匙

    采用RSA算法对网络数据进行加密传输,采用这种加密方式需要两串密匙,公开的叫公匙,没有公开的就叫私匙,公匙和私匙都可以用来加密解密文件,私匙加密的文件公匙解密同理公匙加密的文件可以用私匙来解密。
  2. 公匙和私匙是同时存在的一对密匙

    在本质上没有啥区别,只是统称人人都知道的就叫做公匙,只有自己知道的叫做私匙,这种公私的叫法其实是根据使用习惯来人为赋予的。

  3. 关于双钥加密适用于支付的对接

    它可以保证信息的来源可靠性和信息的完整性。双钥加密就是生成两套密匙。例:A(私)a(公),B(私)b(公),此时甲拿着Ab,乙拿着aB,此时甲与乙通信,甲把内容使用A加密发送给乙,乙使用a解密内容;乙回复甲,乙使用B对内容加密发送给甲,甲使用b对内容解密。

  4. 图例

双钥加密.png

php关于RSA应用

生成

  1. 确定openssl.cnf时候存在
    例如windows下
'e:/wnmp/php8.1.12/extras/ssl/openssl.cnf'
  1. 生成公匙私匙
    基础配置
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();
    }
  1. 生成公匙私匙
/**
     * 生成公匙密匙
     * @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;
    }
}

关于加密

  1. 对于要加密的数据要严格按照密匙说生成的位数来约定长度,如果字符串长度太长超过密匙位数约定长度,则会失败并报告长度超过限制
//指定使用多少位 来生成密匙
'private_key_bits' => 2048,
  1. 错误提示
//函数返回openSSL错误消息,成功返回错误信息字符串,如果没有错误信息返回false
openssl_error_string()
最后修改:2023 年 06 月 30 日
如果觉得我的文章对你有用,请随意赞赏