2025-03-12 10:47:34 +08:00

201 lines
5.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* +----------------------------------------------------------------------
* | CRMEB [ CRMEB赋能开发者助力企业发展 ]
* +----------------------------------------------------------------------
* | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
* +----------------------------------------------------------------------
* | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
* +----------------------------------------------------------------------
* | Author: CRMEB Team <admin@crmeb.com>
* +----------------------------------------------------------------------
*/
namespace crmeb\utils;
use think\exception\ValidateException;
/**
* Class Rsa
* @author 等风来
* @email 136327134@qq.com
* @date 2023/5/16
* @package crmeb\utils
*/
class Rsa
{
/**
* @var string
*/
protected $publicKey;
/**
* @var string
*/
protected $privateKey;
/**
* @var string
*/
protected $basePath;
/**
* 获取证书文件
* @param $publicKey
* @param $privateKey
*/
public function __construct(string $publicKey = 'cert_public_password.key', string $privateKey = 'cert_private_password.key')
{
$this->basePath = app()->getRootPath();
if ($publicKey) {
$this->publicKey = $this->basePath . $publicKey;
}
if ($privateKey) {
$this->privateKey = $this->basePath . $publicKey;
}
if (!is_file($this->publicKey) || !is_file($this->privateKey)) {
$this->exportOpenSSLFile();
}
}
/**
* @return false|string
* @author 等风来
* @email 136327134@qq.com
* @date 2023/5/16
*/
public function getPublicKey()
{
if (!is_file($this->publicKey)) {
$this->exportOpenSSLFile();
}
return file_get_contents($this->publicKey);
}
/**
* 生成证书
* @return bool
*/
public function exportOpenSSLFile($passwork = null)
{
$publicKey = $privateKey = '';
$dir = app()->getRootPath() . 'runtime/conf';
$conf = 'openssl.cnf';
if (!is_dir($dir)) {
mkdir($dir, 0700);
}
if (!file_exists($conf)) {
touch($dir . '/' . $conf);
}
//参数设置
$config = [
"digest_alg" => "sha256",
//字节数 512 1024 2048 4096 等
"private_key_bits" => 1024,
"config" => $dir . '/' . $conf,
//加密类型
"private_key_type" => OPENSSL_KEYTYPE_RSA,
];
//创建私钥和公钥
$res = openssl_pkey_new($config);
if ($res == false) {
//创建失败,请检查openssl.cnf文件是否存在
return false;
}
//将密钥导出为PEM编码的字符串并输出通过引用传递
openssl_pkey_export($res, $privateKey, $passwork, $config);
$publicKey = openssl_pkey_get_details($res);
$publicKey = $publicKey["key"];
//生成证书
$createPublicFileRet = file_put_contents($this->publicKey, $publicKey);
$createPrivateFileRet = file_put_contents($this->privateKey, $privateKey);
if (!($createPublicFileRet || $createPrivateFileRet)) {
return false;
}
openssl_free_key($res);
return true;
}
/**
* 数据加密
* @param string $data
* @param string|null $passwork
* @return false|string
* @author 等风来
* @email 136327134@qq.com
* @date 2023/5/16
*/
function privateEncrypt(string $data, string $passwork = null)
{
$encrypted = '';
$pi_key = openssl_pkey_get_private(file_get_contents($this->privateKey), $passwork);//这个函数可用来判断私钥是否是可用的可用返回资源id Resource id
//最大允许加密长度为117得分段加密
$plainData = str_split($data, 100);//生成密钥位数 1024 bit key
foreach ($plainData as $chunk) {
$partialEncrypted = '';
$encryptionOk = openssl_private_encrypt($chunk, $partialEncrypted, $pi_key);//私钥加密
if ($encryptionOk === false) {
return false;
}
$encrypted .= $partialEncrypted;
}
$encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符需要编码转换下在网络间通过url传输时要注意base64编码是否是url安全的
return $encrypted;
}
/**
* RSA公钥解密(私钥加密的内容通过公钥可以解密出来)
* @param string $public_key 公钥
* @param string $data 私钥加密后的字符串
* @return string $decrypted 返回解密后的字符串
* @author mosishu
*/
function publicDecrypt(string $data)
{
$decrypted = '';
$pu_key = openssl_pkey_get_public(file_get_contents($this->publicKey));//这个函数可用来判断公钥是否是可用的
$plainData = str_split(base64_decode($data), 128);//生成密钥位数 1024 bit key
foreach ($plainData as $chunk) {
$str = '';
$decryptionOk = openssl_public_decrypt($chunk, $str, $pu_key);//公钥解密
if ($decryptionOk === false) {
return false;
}
$decrypted .= $str;
}
return $decrypted;
}
/**
* 私钥解密
* @param string $data
* @return mixed
* @author 等风来
* @email 136327134@qq.com
* @date 2023/5/16
*/
public function privateDecrypt(string $data)
{
if (!is_file($this->privateKey)) {
$this->exportOpenSSLFile();
}
$res = openssl_private_decrypt(base64_decode($data), $decryptedData, file_get_contents($this->privateKey));
if (false === $res) {
throw new ValidateException('RSA:解密失败');
}
return $decryptedData;
}
}