Files
2026-10-14 14:00:29 +08:00

293 lines
8.4 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace encryption;
class Rsa
{
const SIGN_CERT_PWD = '123456'; // 签名证书密码
private $public_key; // 公钥
private $private_key; // 私钥
private $cert_save_path = ''; // 证书文件保存目录
private $openssl_cnf_path = '/etc/ssl/openssl.cnf';
protected static $rsa;
/**
* 设私有构造方法防止对象被new
*/
private function __construct($config)
{
if ($config['public'] && $config['private']) {
if (is_file($config['public'])) {
$this->public_key = $this->getPublicKey($config['public']);
} else {
$this->public_key = openssl_pkey_get_public($config['public']);
if (!$this->public_key) {
die('请检查公钥是否正确');
}
}
if (is_file($config['private'])) {
$this->private_key = $this->getPrivateKey($config['private']);
} else {
$this->private_key = openssl_pkey_get_private($config['private']);
if (!$this->private_key) {
die('请检查私钥是否正确');
}
}
}
if ($config['cert_save_path']) $this->cert_save_path = $config['cert_save_path'];
}
/**
* 单例获取对象实例
*/
public static function instance($config=array())
{
if (!self::$rsa) {
if (empty($config)) {
$config = [
'public' => '',
'private' => '',
'cert_save_path' => ''
];
}
self::$rsa = new self($config);
}
return self::$rsa;
}
/**
* 读取文件
*/
private function fileGet($file)
{
if (!file_exists($file)) {
die($file . "不是文件");
}
return file_get_contents($file);
}
/**
* 获取公钥
*/
private function getPublicKey($path)
{
$pubKey = $this->fileGet($path);
if (!$pubKey) {
die('请检查公钥路径是否正确');
}
return openssl_pkey_get_public($pubKey);
}
/**
* 获取私钥
*/
private function getPrivateKey($path)
{
$priKey = $this->fileGet($path);
if (!$priKey) {
die('请检查私钥路径是否正确');
}
return openssl_pkey_get_private($priKey);
}
/**
* 使用私钥生成签名
* @param string 用于生成签名的字符串
* @return string 签名后的值
*/
public function signPrivate($data)
{
$signature = false;
if (openssl_sign($data, $signature, $this->private_key)) {
$signature = base64_encode($signature);
}
return $signature;
}
/**
* 使用公钥验签
* @param $data = array('data'='','signature'='')
* @return bool
*/
public function verifyPublic($data)
{
$bool = false;
if (!$data['data'] || !$data['signature']) {
die('数据源或签名值为出错!');
}
$result = base64_decode($data['signature']);
switch (openssl_verify($data['data'], $result, $this->public_key)) {
case 1:
$bool = true;
break;
case 0:
case -1:
$bool = false;
break;
default:
$bool = false;
}
return $bool;
}
/**
* 使用公钥加密
*/
public function encryptPublic($data)
{
$crypted = false;
if (is_array($data)) {
$data = json_encode($data);
}
$cryp = strrev($data); // 将数据前后反转再加密
if (openssl_public_encrypt($cryp, $crypted, $this->public_key, OPENSSL_PKCS1_PADDING)) {
$crypted = base64_encode($crypted);
}
return $crypted;
}
/**
* 使用公钥分块加密
*/
public function chunkEncryptPublic($data, $limit = 117)
{
if (is_array($data)) {
$data = json_encode($data);
}
$datas = str_split($data, $limit);
$crypteds = [];
foreach ($datas as $key => $val) {
$crypteds[$key] = $this->encryptPublic($val);
}
return $crypteds;
}
/**
* 使用私钥解密
*/
public function decryptPrivate($encrypted)
{
$decrypted = '';
$data = base64_decode($encrypted);
if (openssl_private_decrypt($data, $decrypted, $this->private_key, OPENSSL_PKCS1_PADDING)) {
$decrypted = rtrim(strrev($decrypted), '\0');
}
return $decrypted;
}
/**
* 使用私钥分块解密
*/
public function chunkDecryptPrivate($encrypteds)
{
$decrypted = '';
$encrypteds = htmlspecialchars_decode($encrypteds);
if (!is_array($encrypteds)) {
$arr = explode(',', $encrypteds);
if ($arr) {
$encrypteds = $arr;
} else {
return json_decode($this->decryptPrivate($encrypteds));
}
}
foreach ($encrypteds as $key => $val) {
$decrypted .= $this->decryptPrivate($val);
}
$res = json_decode($decrypted, true);
if (is_array($res)) return $res;
return json_decode($res, true);
}
/**
* 生成公私钥
*/
public function createRsa($writeFile=false)
{
$config = array("config" => $this->openssl_cnf_path);
// 生成公私钥
$privkey = openssl_pkey_new($config);
openssl_pkey_export($privkey, $private_key, null, $config); // 导出私钥$private_key
$public_key = openssl_pkey_get_details($privkey); // 导出公钥$public_key
if (!$writeFile) {
return array('private_key' => $private_key, 'public_key' => $public_key['key']);
}
$publicPath = $this->cert_save_path . "rsa_public_key.pem"; // 生成公钥路径
$privatePath = $this->cert_save_path . "rsa_private_key.pem"; // 私钥文件路径
// 生成公钥文件
if (!is_writeable($publicPath)) {
chmod($publicPath, 0755);
}
$fp = fopen($publicPath, "w");
fwrite($fp, $public_key['key']);
fclose($fp);
// 生成私钥文件
if (!is_writeable($privatePath)) {
chmod($privatePath, 0755);
}
$fp = fopen($privatePath, "w");
fwrite($fp, $private_key);
fclose($fp);
}
/**
* 生成证书和密钥
*/
public function createCsr($writeFile=false)
{
$dn = array(
"countryName" => 'CN', // 所在国家名称
"stateOrProvinceName" => 'Hunan', // 所在省份名称
"localityName" => 'Changsha', // 所在城市名称
"organizationName" => 'opd', // 注册人姓名
"organizationalUnitName" => 'orico_opd', // 组织名称
"commonName" => 'orico_opd', // 公共名称
"emailAddress" => '735273025@qq.com' // 邮箱
);
$privkeypass = self::SIGN_CERT_PWD; //私钥密码
$config = array(
"config" => $this->openssl_cnf_path,
"digest_alg" => "sha1",
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_DSA,
"encrypt_key" => false
);
$privkey = openssl_pkey_new($config);
$csr = openssl_csr_new($dn, $privkey, $config);
$sscert = openssl_csr_sign($csr, null, $privkey, 365, $config);
openssl_x509_export($sscert, $csrkey); // 导出证书$csrkey 
openssl_pkcs12_export($sscert, $private_key, $privkey, $privkeypass); // 导出密钥$private_key 
if (!$writeFile) {
return array('csrkey' => $csrkey, 'private_key_pfx' => $private_key);
}
$cerpath = $this->cert_save_path . "csrkey.cer"; // 生成证书路径
$pfxpath = $this->cert_save_path . "private_key.pfx"; // 密钥文件路径
// 生成证书文件
if (!is_writeable($cerpath)) {
chmod($cerpath, 0755);
}
$fp = fopen($cerpath, "w");
fwrite($fp, $csrkey);
fclose($fp);
// 生成密钥文件
if (!is_writeable($pfxpath)) {
chmod($pfxpath, 0755);
}
$fp = fopen($pfxpath, "w");
fwrite($fp, $private_key);
fclose($fp);
}
}