不败君

前端萌新&初级后端攻城狮

PHP长文本非对称密钥加解密

PHP长文本非对称密钥加解密

2024-04-12 18:03:00

围观(1557)

class RSA
{
    // 公钥
    private $publicKey  = __DIR__ . './rsa/publicKey.pem';
    // 私钥
    private $privateKey = __DIR__ . './rsa/privateKey.pem';

    // 需要用到环境配置文件 openssl.cnf
    // 更改为您的 openssl.cnf 文件路径
    private $configPath = 'D:\\xxx\\openssl.cnf';

    private $publicResource;
    private $privateResource;

    public function __construct()
    {
        if (empty($this->publicResource) || empty($this->privateResource)) {
            $this->setResource();
        }
    }

    /**
     * 生成公钥和私钥对
     * @return void
     */
    private function createRsaKey(): void
    {
        $config = [
            'digest_alg'       => 'sha512',
            'private_key_bits' => 4096,
            'private_key_type' => OPENSSL_KEYTYPE_RSA,
            'config'           => realpath($this->configPath),
        ];
        @mkdir(dirname($this->publicKey), 0777, true);
        @mkdir(dirname($this->privateKey), 0777, true);
        $newKey = openssl_pkey_new($config);
        if (!$newKey) {
            return;
        }
        openssl_pkey_export($newKey, $privateKey, null, $config);
        $publicKey = openssl_pkey_get_details($newKey);
        // 公钥
        file_put_contents($this->publicKey, $publicKey['key']);
        // 密钥
        file_put_contents($this->privateKey, $privateKey);
        openssl_free_key($newKey);
    }

    private function setResource()
    {
        if (!file_exists($this->publicKey) || !file_exists($this->privateKey)) {
            $this->createRsaKey();
        }
        $publicKey            = file_get_contents($this->publicKey);
        $this->publicResource = openssl_pkey_get_public($publicKey);
        if (!$this->publicResource) {
            throw new Exception('公钥载入失败:' . openssl_error_string());
        }
        $privateKey            = file_get_contents($this->privateKey);
        $this->privateResource = openssl_pkey_get_private($privateKey);
        if (!$this->privateResource) {
            throw new Exception('私钥载入失败:' . openssl_error_string());
        }
    }

    /**
     * 公钥加密
     * @param $str
     * @return string
     * @throws Exception
     */
    public function publicEncrypt($str): string
    {
        return $this->encrypt($str);
    }

    /**
     * 私钥加密
     * @param $str
     * @return string
     * @throws Exception
     */
    public function privateEncrypt($str): string
    {
        return $this->encrypt($str, 1);
    }

    /**
     * 加密
     * @param $str
     * @param int $type
     * @return string
     * @throws Exception
     */
    private function encrypt($str, int $type = 0): string
    {
        $resource        = $this->publicResource;
        $encryptFunction = 'openssl_public_encrypt';
        if ($type) {
            // 私钥加密
            $resource        = $this->privateResource;
            $encryptFunction = 'openssl_private_encrypt';
        }
        $rows   = str_split($str, 117);
        $result = [];
        foreach ($rows as $row) {
            $res        = '';
            $encryptRes = $encryptFunction($row, $res, $resource);
            if (!$encryptRes) {
                throw new Exception('加密失败:' . openssl_error_string());
            }
            $result[] = base64_encode($res);
        }
        return base64_encode(json_encode($result));
    }

    /**
     * 私钥解密
     * @param $str
     * @return string
     * @throws Exception
     */
    public function privateDecrypt($str): string
    {
        return $this->decrypt($str);
    }

    /**
     * 公钥解密
     * @param $str
     * @return string
     * @throws Exception
     */
    public function publicDecrypt($str): string
    {
        return $this->decrypt($str, 1);
    }

    /**
     * 解密
     * @param $str
     * @param int $type
     * @return string
     * @throws Exception
     */
    private function decrypt($str, int $type = 0): string
    {
        $resource        = $this->privateResource;
        $decryptFunction = 'openssl_private_decrypt';
        if ($type) {
            $resource        = $this->publicResource;
            $decryptFunction = 'openssl_public_decrypt';
        }
        $rows   = json_decode(base64_decode($str), true);
        $result = '';
        foreach ($rows as $row) {
            $res        = '';
            $decryptRes = $decryptFunction(base64_decode($row), $res, $resource);
            if (!$decryptRes) {
                throw new Exception('解密失败:' . openssl_error_string());
            }
            $result .= $res;
        }
        return $result;
    }
}

$rsa = new RSA;

// 要加密的字符串
$str = 'RSA算法是一种非对称加密算法,与对称加密算法不同的是,RSA算法有两个不同的密钥,一个是公钥,一个是私钥。 [10]
RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 [2]。
在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK [2]。
正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要 [2]。
RSA是被研究得最广泛的公钥算法,从提出后经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。1983年麻省理工学院在美国为RSA算法申请了专利 [3]。
RSA允许选择公钥的大小。512位的密钥被视为不安全的;768位的密钥不用担心受到除了国家安全管理(NSA)外的其他事物的危害;RSA在一些主要产品内部都有嵌入';

// 公钥加密
$encryptStr = $rsa->publicEncrypt($str);
echo "公钥加密生成的字符串:" . $encryptStr;
echo "\\n\\n ----- \\n\\n";
// 私钥解密
$decryptStr = $rsa->privateDecrypt($encryptStr);
echo "私钥解密结果:" . $decryptStr;

echo "\\n\\n ----- \\n\\n";

// 私钥加密
$encryptStr = $rsa->privateEncrypt($str);
echo "私钥加密生成的字符串:" . $encryptStr;
echo "\\n\\n ----- \\n\\n";
// 公钥解密
$decryptStr = $rsa->publicDecrypt($encryptStr);
echo "公钥解密结果:" . $decryptStr;


本文地址 : bubaijun.com/page.php?id=239

版权声明 : 未经允许禁止转载!

上一篇文章: 接入京东联盟的一些坑

下一篇文章: 暂无

评论:我要评论

jiyouzhan 沙发

这篇文章写得深入浅出,让我这个小白也看懂了!

评论时间:2024-05-19 13:38:05

回复

发布评论:
Copyright © 不败君 粤ICP备18102917号-1

不败君

首 页 作 品 微 语