PHP RSA生成公钥和私钥对及加解密
基于PHP OpenSSL 扩展 生成RSA密钥对,和RSA加密解密,且支持长文加密和解密。
条件:
需要安装开启OpenSSL扩展。
PHP RSA 效果:
1、RSA RSA生成公钥和私钥对>> RSA 密钥生成
2、RSA加密解密,且支持长文加密和解密 >> RSA 公钥/私钥加解密
PHP RSA处理类:
<?php /** * PHP RSA生成公钥和私钥对及加解密 */ namespace rsa; class RsaHandle { /** * RsaHandle constructor. * @throws \Exception */ public function __construct() { //检查 扩展是否安装 if (extension_loaded('openssl') == false){ $msg = "请先安装开启openssl扩展"; throw new \Exception($msg); } } /** * 创建生成密钥 公钥私钥 * @param int $private_key_bits 指定多少位来生成私钥 //字节数 512 1024 2048 4096 等 ,不能加引号,此处长度与加密的字符串长度有关系 * @return array */ public function createRsaKey($private_key_bits = 1024) { //参考文章 //https://www.cnblogs.com/guliang/p/16171260.html //配置信息 $config = array( //'digest_alg' => 'sha512', 'private_key_bits' => $private_key_bits,//指定多少位来生成私钥 //字节数 512 1024 2048 4096 等 ,不能加引号,此处长度与加密的字符串长度有关系 'private_key_type' => OPENSSL_KEYTYPE_RSA //加密类型 ); $system_name = PHP_OS; if ($system_name === "WINNT"){ //windows系统 //报错 openssl_pkey_export(): cannot get key from parameter 1这个问题 是 没有找到 config cnf 文件路径,我这里用的是PHPstudy Apache 目录有 直接指向 就可 //https://blog.csdn.net/jachinFang/article/details/94598969 //将apache中的openssl.cnf复制 $config['config'] 进去,然后就可以尝试测试结果了 $config['config'] = 'D:\phpstudy_pro\Extensions\Apache2.4.39\conf/openssl.cnf';//找到你的PHP目录下openssl配置文件 } $res = openssl_pkey_new($config); //获取私钥 openssl_pkey_export($res, $private_key, null, $config); //获取公钥 $details = openssl_pkey_get_details($res); $public_key = $details['key']; return array('public_key' => $public_key, 'private_key' => $private_key); } /** * 获取密钥分段加密长度. * @param $keyClosure openssl_pkey_get_public($this->config['publicKey']) : openssl_pkey_get_private($this->config['privateKey']); * @return float|int * @throws \Exception */ protected function getEncryptBlockLen($keyClosure) { $key_info = openssl_pkey_get_details($keyClosure); if (!$key_info) { $msg = '获取加密密钥信息失败' . openssl_error_string(); throw new \Exception($msg); } // bits数除以8 减去padding长度,OPENSSL_PKCS1_PADDING 长度是11 // php openssl 默认填充方式是 OPENSSL_PKCS1_PADDING return $key_info['bits'] / 8 - 11; } /** * 获取密钥分段解密长度. * @param $keyClosure openssl_pkey_get_public($this->config['publicKey']) : openssl_pkey_get_private($this->config['privateKey']); * @return float|int * @throws \Exception */ protected function getDecryptBlockLen($keyClosure) { $key_info = openssl_pkey_get_details($keyClosure); if (!$key_info) { $msg = '获取解密密钥信息失败' . openssl_error_string(); throw new \Exception($msg); } // bits数除以8得到字符长度 return $key_info['bits'] / 8; } /** * 公钥加密 * @param $text * @param string $public_key * @return string * @throws \Exception */ public function rsaEncodePublic($text, $public_key = '公钥加密私钥解密') { $keyClosure = openssl_pkey_get_public($public_key); if (!$keyClosure) { $msg = '公钥不可用'; throw new \Exception($msg); } //RSA进行加密 $encrypt = ''; $plainData = str_split($text, $this->getEncryptBlockLen($keyClosure)); foreach ($plainData as $key => $encrypt_item) { $isEncrypted = openssl_public_encrypt($encrypt_item, $encrypted, $keyClosure); if (!$isEncrypted) { $msg = '加密数据失败,请检查密钥是否合法,' . openssl_error_string(); throw new \Exception($msg); } $encrypt .= $encrypted; } $encrypt = base64_encode($encrypt); //返回 return $encrypt; } /** * 私钥加密 * @param $text * @param string $private_key * @return string * @throws \Exception */ public function rsaEncodePrivate($text, $private_key = '私钥加密公钥解密') { $keyClosure = openssl_pkey_get_private($private_key); if (!$keyClosure) { $msg = '私钥不可用'; throw new \Exception($msg); } //RSA进行加密 $encrypt = ''; $plainData = str_split($text, $this->getEncryptBlockLen($keyClosure)); foreach ($plainData as $key => $encrypt_item) { $isEncrypted = openssl_private_encrypt($encrypt_item, $encrypted, $keyClosure); if (!$isEncrypted) { $msg = '加密数据失败,请检查密钥是否合法,' . openssl_error_string(); throw new \Exception($msg); } $encrypt .= $encrypted; } $encrypt = base64_encode($encrypt); //返回 return $encrypt; } /** * 私钥解密 * @param $text * @param string $private_key * @return string * @throws \Exception */ public function rsaDecodePrivate($text,$private_key = '公钥加密私钥解密') { $keyClosure = openssl_pkey_get_private($private_key); if (!$keyClosure) { $msg = '私钥不可用'; throw new \Exception($msg); } //RSA进行解密 $data = base64_decode($text); $data = str_split($data, $this->getDecryptBlockLen($keyClosure)); $decrypt = ''; foreach ($data as $key => $chunk) { $isDecrypted = openssl_private_decrypt($chunk, $encrypted, $keyClosure); if (!$isDecrypted) { $msg = '解密数据失败,请检查密钥是否合法,' . openssl_error_string(); throw new \Exception($msg); } $decrypt .= $encrypted; } //返回 return $decrypt; } /** * 公钥解密 * @param $text * @param string $public_key * @return string * @throws \Exception */ public function rsaDecodePublic($text,$public_key = '私钥加密公钥解密') { $keyClosure = openssl_pkey_get_public($public_key); if (!$keyClosure) { $msg = '公钥不可用'; throw new \Exception($msg); } //RSA进行解密 $data = base64_decode($text); $data = str_split($data, $this->getDecryptBlockLen($keyClosure)); $decrypt = ''; foreach ($data as $key => $chunk) { $isDecrypted = openssl_public_decrypt($chunk, $encrypted, $keyClosure); if (!$isDecrypted) { $msg = '解密数据失败,请检查密钥是否合法,' . openssl_error_string(); throw new \Exception($msg); } $decrypt .= $encrypted; } //返回 return $decrypt; } }
参考文章:
https://php.net/manual/en/function.openssl-pkey-new.php
https://www.cnblogs.com/guliang/p/16171260.html
https://blog.csdn.net/jachinFang/article/details/94598969