注:加密的内容长度是有限制的,具体可参考
密钥生成
https://www.jianshu.com/p/9dc5c8a93308
https://blog.csdn.net/li396864285/article/details/79865806
A为客户端 B为服务端
A手里有一套密钥(私钥A/公钥A)
B手里有一套密钥(私钥B/公钥B)
A将公钥A发给B
B将公钥B发给A
注:两套公钥目的是为了保证确实是AB双方在通信,双方的私钥加签是为了标明自己的身份,如果只是对数据进行保护,防止被窃取,服务器只颁发一套密钥也可以
A向B发送请求流程:
2. A用 私钥A + msg获取签名SignA
3. A用 公钥B 将SignA + msg 加密 得到 要发送的密文 secret
4. B 收到 A 发送过来的密文 secret 使用 私钥B 进行解密 得到 SignA + msg (第一次解密)
5. B 使用 公钥B + msg +signA进行验签操作(第二次验签)
/**
* Created by PhpStorm.
* User: 80752
* Date: 2018/9/12
* Time: 21:30
*/
if (! function_exists('url_safe_base64_encode')) {
function url_safe_base64_encode ($data) {
return str_replace(array('+','/', '='),array('-','_', ''), base64_encode($data));
}
}
if (! function_exists('url_safe_base64_decode')) {
function url_safe_base64_decode ($data) {
$base_64 = str_replace(array('-','_'),array('+','/'), $data);
return base64_decode($base_64);
}
}
class RSA
{
/**
* 选择在创建CSR时应该使用哪些扩展。可选值有 OPENSSL_KEYTYPE_DSA, OPENSSL_KEYTYPE_DH, OPENSSL_KEYTYPE_RSA 或 OPENSSL_KEYTYPE_EC. 默认值是 OPENSSL_KEYTYPE_RSA.
*/
const RSA_ALGORITHM_KEY_TYPE = OPENSSL_KEYTYPE_RSA;
/**
* 签名算法, 默认为 OPENSSL_ALGO_SHA1
*/
const RSA_ALGORITHM_SIGN = OPENSSL_ALGO_SHA256;
/**
* 公钥
* @var string
*/
public static $publicKey = '';
/**
* 私钥
* @var string
*/
public static $privateKey = '';
public static function createRsaKey ($key_size = 2048) {
$config = array(
"private_key_bits" => $key_size,
"private_key_type" => self::RSA_ALGORITHM_KEY_TYPE
);
$res = openssl_pkey_new($config);
openssl_pkey_export($res, $private_key);
$public_key_detail = openssl_pkey_get_details($res);
$public_key = $public_key_detail["key"];
self::$publicKey = $public_key;
self::$privateKey = $private_key;
return [
"public_key" => $public_key,
"private_key" => $private_key,
];
}
/**
* 获取rsa密钥加密位数
* @param $source
* @return mixed
*/
private static function getKeyBitDetail ($source) {
return openssl_pkey_get_details($source)['bits'];
}
/**
* 获取私钥
* @return bool|resource
*/
public static function getPrivateKey () {
$source = openssl_pkey_get_private('file://rsa_private_key.pem');
if (!$source) {
$source = openssl_pkey_get_private(self::$privateKey);
}
return $source;
}
/**
* 获取公钥
* @return resource
*/
public static function getPublicKey () {
$source = openssl_pkey_get_public('file://rsa_public_key.pem');
if (!$source) {
$source = openssl_pkey_get_public(self::$publicKey);
}
return $source;
}
/**
* 私钥加密
* @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 ? 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(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 ? 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(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 string $data
* @return null|string
*/
public static function privSign ($data = '') {
$privKey = self::getPrivateKey();
openssl_sign($data, $sign, $privKey, self::RSA_ALGORITHM_SIGN);
openssl_free_key($privKey);
return $sign ? url_safe_base64_encode($sign) : null;
}
/**
* 公钥验签
* @param string $data
* @param string $sign
* @return int
*/
public static function publicVerifySign ($data = '', $sign = '') {
$pubKey = self::getPublicKey();
$res = openssl_verify($data, url_safe_base64_decode($sign), $pubKey, self::RSA_ALGORITHM_SIGN);
openssl_free_key($pubKey);
return $res;
}
}
$data['name'] = 'sowork111111111111111111111111111111111111111111111111sowork1111111111111111111111111111111111112313111111111111111111111111===============================================';
$data['age'] = '24';
echo '<pre>';
print_r(RSA::createRsaKey()) . '<br/>';
echo '</pre>';
// 私钥加密 公钥解密
//$privSec = RSA::privEncrypt(json_encode($data));
//echo '私钥加密:' . $privSec . '<br/>';
//echo '公钥解密:' . RSA::publicDecrypt($privSec) . '<br/>';
// 公钥加密 私钥解密
//$pubSec = RSA::publicEncrypt(json_encode($data));
//echo '公钥加密:' . $pubSec . '<br/>';
//echo '私钥解密:' . RSA::privDecrypt($pubSec) . '<br/>';
$sign = RSA::privSign(json_encode($data));
$secret = RSA::publicEncrypt(json_encode($data));
echo '私钥签名后:' . $sign . ' <br/>';
echo '公钥验签后:' . RSA::publicVerifySign(json_encode($data), $sign) . '<br/>';