前言:
RSA,常说的非对称加密。加密解密密钥不一致,它们是成对出现,通常密钥生成是PEM格式。
公钥加密的私钥解密,私钥加密的要公钥解密
。
往往私钥是不公开的,公钥是大家共享的。 相同内容,相同私钥每次加密后结果还会不一样。 通过公钥加密结果,必须私钥解密。
同样私钥加密结果,公钥可以解密。 RSA加密也是块加密,因此一样存在填充模式。pkcs#1与pkcs#8
默认填充方式是pkcs#1。
注:php 目前只支持 pkcs#1的填充模式
工具类
/**
* RSA算法类
* 签名及密文编码:base64字符串/十六进制字符串/二进制字符串流
* 填充方式: PKCS1Padding(加解密)/NOPadding(解密)
*
* Notice:Only accepts a single block. Block size is equal to the RSA key size!
* 如密钥长度为1024 bit,则加密时数据需小于128字节,加上PKCS1Padding本身的11字节信息,所以明文需小于117字节
*/
class Rsa
{
private $pubKey = null;
private $priKey = null;
/**
* 构造函数
*
* @param string 公钥文件(验签和加密时传入)
* @param string 私钥文件(签名和解密时传入)
*/
public function __construct($public_key_file = '', $private_key_file = '')
{
// 需要开启openssl扩展
if (!extension_loaded("openssl")) {
$this->_error("Please open the openssl extension first.");
}
// 没有就生成一对
if (!file_exists($private_key_file) || !file_exists($public_key_file)) {
$key = $this->generate();
file_put_contents($private_key_file, $key['private_key'], LOCK_EX);
file_put_contents($public_key_file, $key['public_key'], LOCK_EX);
}
if ($public_key_file) {
$this->_getPublicKey($public_key_file);
}
if ($private_key_file) {
$this->_getPrivateKey($private_key_file);
}
}
/**
* 生成Rsa公钥和私钥
* @param int $private_key_bits 建议:[512, 1024, 2048, 4096]
* @return array
*/
public function generate(int $private_key_bits = 1024)
{
$rsa = [
"private_key" => "",
"public_key" => ""
];
$config = [
"digest_alg" => "sha512",
"private_key_bits" => $private_key_bits, #此处必须为int类型
"private_key_type" => OPENSSL_KEYTYPE_RSA,
];
//创建公钥和私钥
$res = openssl_pkey_new($config);
//提取私钥
openssl_pkey_export($res, $rsa['private_key']);
//生成公钥
$rsa['public_key'] = openssl_pkey_get_details($res)["key"];
/*Array
(
[bits] => 512
[key] =>
[rsa] =>
[type] => 0
)*/
return $rsa;
}
// 私有方法
/**
* 自定义错误处理
*/
private function _error($msg)
{
die('RSA Error:' . $msg);
}
/**
* 检测填充类型
* 加密只支持PKCS1_PADDING
* 解密支持PKCS1_PADDING和NO_PADDING
*
* @param int 填充模式
* @param string 加密en/解密de
* @return bool
*/
private function _checkPadding($padding,