2024-04-12 18:03:00
围观(5118)
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;