函数明细
openssl_pkey_get_details
返回包含密钥详情的数组,如类型type,加密位数bits等openssl_pkey_get_private
获取私钥
只能打开是PEM格式的秘钥,成功返回资源类型
openssl_pkey_get_public
获取公钥
只能打开是PEM格式的秘钥,成功返回资源类型
openssl_private_encrypt
使用私钥加密数据
加密后的数据可以通过openssl_public_decrypt()函数来解密 该函数用来签名数据(或者哈希)让别人相信数据并不是其他人写的
openssl_public_decrypt
解密先前由 openssl_private_encrypt() 加密的数据,并且将结果保存至第二个参数中
你可以用该函数来校验消息是否是私钥拥有者写的。
openssl_public_encrypt
使用公钥加密数据
该函数可以用来加密数据,供该公钥匹配的私钥拥有者读取。 它也可以用来在数据库中存储安全数据。
openssl_private_decrypt
使用私钥解密数据
openssl_private_decrypt() 解密先前通过 openssl_public_encrypt() 函数加密的 data 你可以用该函数来解密只对你可用的数据。
openssl_sign
生成签名,通过使用与之关联的私钥生成加密数字签名来计算指定的签名openssl_verify
验证签名,通过使用关联的公钥验证指定数据的签名是否正确, 通过返回int 1openssl_free_key
从内存中释放密钥资源
用例解析
代码语言:javascript复制/**
* 通用rsa认证与加密类
*
* @author litblc
* User: z00455118
* Date: 2019/7/15
* Time: 19:20
*/
class RSA
{
/**
* 签名算法, 默认为 OPENSSL_ALGO_SHA1
*/
const RSA_ALGORITHM_SIGN = OPENSSL_ALGO_SHA256;
/**
* 公钥
* @var string
*/
private static $publicKey = 'file:///D:/cert/public-key.pem';
/**
* 私钥
* @var string
*/
private static $privateKey = 'file:///D:/cert/private-key.pem';
/**
* 第三方公钥 交互验签使用
* @var string
*/
private static $thirdPublicKey = 'file:///D:/cert/third-public-key.pem';
/**
* 初始化秘钥信息
* @var string
*/
public function __construct($config)
{
self::$publicKey = CERT_DIR . $config['publicKey'];
self::$privateKey = CERT_DIR . $config['privateKey'];
self::$thirdPublicKey = CERT_DIR . $config['thirdPublicKey'];
}
/**
* 是否使用安全base64需要参考第三方验签的解析方案,如果也是php推荐使用安全方式
* @param $data
* @return string
*/
private static function url_safe_base64_encode($data)
{
return str_replace([' ', '/', '='], ['-', '_', ''], base64_encode($data));
}
/**
* @param $data
* @return string
*/
private static function url_safe_base64_decode($data)
{
$base_64 = str_replace(['-', '_'], [' ', '/'], $data);
return base64_decode($base_64);
}
/**
* 获取rsa密钥加密位数
* @param $source
* @return mixed
*/
private static function getKeyBitDetail($source)
{
return openssl_pkey_get_details($source)['bits'];
}
/**
* 获取文本格式私钥 并重新格式化 为保证任何key都可以识别
* 由于各个语言以及环境使用的证书格式不同。参考下一节: ### 秘钥格式解析
* @return bool|resource
*/
private static function getPrivateKey()
{
if (file_exists(self::$publicKey)) {
$source = file_get_contents(self::$privateKey);
$search = [
"-----BEGIN RSA PRIVATE KEY-----",
"-----END RSA PRIVATE KEY-----",
"n",
"r",
"rn"
];
$private_key = str_replace($search,"",$source);
return openssl_pkey_get_private($search[0] . PHP_EOL . wordwrap($private_key, 64, "n", true) . PHP_EOL . $search[1]);
}
}
/**
* 获取公钥 并重新格式化
* @return resource
*/
private static function getPublicKey()
{
if (file_exists(self::$publicKey)) {
$source = file_get_contents(self::$publicKey);
$search = [
"-----BEGIN PUBLIC KEY-----",
"-----END PUBLIC KEY-----",
"n",
"r",
"rn"
];
$public_key = str_replace($search,"",$source);
return openssl_pkey_get_public($search[0] . PHP_EOL . wordwrap($public_key, 64, "n", true) . PHP_EOL . $search[1]);
}
}
/**
* 获取第三方公钥,并格式化
* @return resource
*/
private static function getPublicKeyThird()
{
if (file_exists(self::$thirdPublicKey)) {
$source = file_get_contents(self::$thirdPublicKey);
$search = [
"-----BEGIN PUBLIC KEY-----",
"-----END PUBLIC KEY-----",
"n",
"r",
"rn"
];
$public_key = str_replace($search, "", $source);
return openssl_pkey_get_public($search[0] . PHP_EOL . wordwrap($public_key, 64, "n", true) . PHP_EOL . $search[1]);
}
}
/**
* 排序数据并生成待验签字符串(类似微信支付,使用此方法,而非例子中json_encode方法)
* @return string
*/
private static function createLinkString($data = [])
{
unset($data['sign']);
foreach ($data as $key => $val) {
if (!$val) {
unset($data[$key]);
}
}
ksort($data);
return urldecode(http_build_query($data));
}
/**
* 排序数据并生成待验签字符串(类似微信支付,使用此方法,而非例子中json_encode方法)
* @return string
*/
public static function createLinkStringNew($data = [])
{
$mac = '';
ksort($data);
unset($data['sign'], $data['sign_type']);
foreach ($data as $key => $val) {
if ($val) {
$mac .= "&{$key}={$val}";
}
}
return ltrim($mac, '&');
}
/**
* 私钥加密
* @param $data
* @return bool|null
*/
public static function privEncrypt($data = '')
{
$privKey = self::getPrivateKey();
$partLen = self::getKeyBitDetail($privKey) / 8 - 11;
$parts = str_split($data, $partLen);
$encrypted = '';
foreach ($parts as $part) {
openssl_private_encrypt($part, $partEncrypt, $privKey);
$encrypted .= $partEncrypt;
}
openssl_free_key($privKey);
return $encrypted ? self::url_safe_base64_encode($encrypted) : null;
}
/**
* 公钥解密
* @param string $encrypted
* @return bool|null
*/
public static function publicDecrypt($encrypted = '')
{
$pubKey = self::getPublicKey();
$partLen = self::getKeyBitDetail($pubKey) / 8;
$parts = str_split(self::url_safe_base64_decode($encrypted), $partLen);
$decrypted = '';
foreach ($parts as $part) {
openssl_public_decrypt($part, $partDecrypt, $pubKey);
$decrypted .= $partDecrypt;
}
openssl_free_key($pubKey);
return $decrypted ?: null;
}
/**
* 公钥加密
* @param string $data
* @return bool|null
*/
public static function publicEncrypt($data = '')
{
$pubKey = self::getPublicKey();
$partLen = self::getKeyBitDetail($pubKey) / 8 - 11;
$parts = str_split($data, $partLen);
$encrypted = '';
foreach ($parts as $part) {
openssl_public_encrypt($part, $partEncrypt, $pubKey);
$encrypted .= $partEncrypt;
}
openssl_free_key($pubKey);
return $encrypted ? self::url_safe_base64_encode($encrypted) : null;
}
/**
* 私钥解密
* @param string $encrypted
* @return bool|null
*/
public static function privDecrypt($encrypted = '')
{
$privKey = self::getPrivateKey();
$partLen = self::getKeyBitDetail($privKey) / 8;
$parts = str_split(self::url_safe_base64_decode($encrypted), $partLen);
$decrypted = '';
foreach ($parts as $part) {
openssl_private_decrypt($part, $partDecrypt, $privKey);
$decrypted .= $partDecrypt;
}
openssl_free_key($privKey);
return $decrypted ?: null;
}
/**
* 私钥签名
* @param array $data
* @return null|string
*/
public static function privSign($data = [])
{
$privKey = self::getPrivateKey();
openssl_sign(self::createLinkStringNew($data), $sign, $privKey, self::RSA_ALGORITHM_SIGN);
openssl_free_key($privKey);
return $sign ? self::url_safe_base64_encode($sign) : null;
}
/**
* 公钥验签
* @param array $data
* @param string $sign
* @return int
*/
public static function publicVerifySign($data = [], $sign = '')
{
$pubKey = self::getPublicKey();
$res = openssl_verify(self::createLinkStringNew($data), self::url_safe_base64_decode($sign), $pubKey, self::RSA_ALGORITHM_SIGN);
openssl_free_key($pubKey);
return $res;
}
/**
* 公钥验签(第三方)
* @param array $data
* @param string $sign
* @return int
*/
public static function publicVerifySignThird($data = [], $sign = '')
{
$pubKey = self::getPublicKeyThird();
$res = openssl_verify(self::createLinkStringNew($data), self::url_safe_base64_decode($sign), $pubKey, self::RSA_ALGORITHM_SIGN);
openssl_free_key($pubKey);
return $res;
}
}
测试输出
代码语言:javascript复制$data['name'] = '网红';
$data['age'] = '26';
$data['title'] = '中华人民共和国公民';
$data['english'] = 'litblc.com';
// 私钥加密 公钥解密
$privSec = RSA::privEncrypt(json_encode($data));
echo '私钥加密:' . $privSec . '<br/>';
echo '公钥解密:' . RSA::publicDecrypt($privSec) . '<br/>';
echo '<hr>';
// 公钥加密 私钥解密
$pubSec = RSA::publicEncrypt(json_encode($data));
echo '公钥加密:' . $pubSec . '<br/>';
echo '私钥解密:' . RSA::privDecrypt($pubSec) . '<br/>';
echo '<hr>';
// 验签
$sign = RSA::privSign($data);
echo '私钥签名后:' . $sign . '<br/>';
echo '公钥验签后:' . RSA::publicVerifySign($data, $sign) . '<br/>';
秘钥格式解析
- X.509、PKCS文件格式介绍
- What are the differences between .P7B (PKCS#7) .PFX/.P12 (PKCS#12) .PEM, .DER, .CRT, .CER Certificates?
- 公钥密码学标准 - wiki
- SSL 证书格式普及,PEM、CER、JKS、PKCS12
- RSA公钥、私钥的生成详解,包含Java、PHP、Android、iOS端