说明:
php服务端与客户端交互、提供开放api时,通常需要对敏感的部分api数据传输进行数据加密,这时候rsa非对称加密就能派上用处了,下面通过一个例子来说明如何用php来实现数据的加密解密
加密解密的第一步是生成公钥、私钥对,私钥加密的内容能通过公钥解密(反过来亦可以)
通过私钥能生成对应的公钥,因此我们将私钥用在服务器端,公钥发放给android、ios等前端
配置:
开启OpenSSL扩展
下载对应php版本文件:https://windows.php.net/downloads/php-sdk/deps/
解压到对应php版本目录下:D:\phpStudy\php\php-5.3.29-nts\extras
生成公钥私钥:
$config = array(
'config' => 'D:\phpStudy\php\php-5.3.29-nts\extras\openssl\openssl.cnf',
'digest_alg' => 'sha512',
'private_key_bits' => 512, //字节数 512 1024 2048 4096 等
'private_key_type' => OPENSSL_KEYTYPE_RSA, //加密类型
);
//创建公钥和私钥 返回资源
$res = openssl_pkey_new($config);
//从得到的资源中获取私钥 并把私钥赋给
openssl_pkey_export($res, $privKey, null, $config);
//从得到的资源中获取公钥 返回公钥
$pubKey = openssl_pkey_get_details($res);
$pubKey = $pubKey["key"];
echo '';
var_dump(array('privKey' => $privKey, 'pubKey' => $pubKey));
使用示例:
//私匙
$private_key = '-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAJmIHQFP5yh8ztq7+vvkdDCGBqTxymVpDDsmrVeGhLqse7NKXS2H
+zzbwXbe19wueQJ90QpElUpUviCg3WhdxMECAwEAAQJAWeXPRgNpUNWzsXQ8g93D
At6XaWGCp1qZJNGC0isb8MlCAHgt+G/y4yMtEmNio/IftpK1qI5SM6ODBcqsEHUB
IQIhAMeJPTB/7pYyx+ShMYQCOLBHM708ANqIPsFnAR1KvY6tAiEAxPo7MH1roobv
Xq9898slHJxD+nXKnaU3BLwzfc9aNOUCIC6HL/+JNWdMvBPyCovPwMxKLiRoQ4Kx
1oBetoHQFdeZAiEAnntaTgxLIowAYaU+HbyTkm5j/0rwh2AbYTLvFuVTBcUCIBj7
oq98J0h9cmd5c9dqLisaKbWZETgWextIAmi0FcyE
-----END RSA PRIVATE KEY-----';
//公匙
$public_key = '-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJmIHQFP5yh8ztq7+vvkdDCGBqTxymVp
DDsmrVeGhLqse7NKXS2H+zzbwXbe19wueQJ90QpElUpUviCg3WhdxMECAwEAAQ==
-----END PUBLIC KEY-----';
$data = json_encode(array('name' => '张三', 'age' => 18));//原始数据 或者是需要加密的数据
$pi_key = openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id
$pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的
//私匙加密公钥解密
openssl_private_encrypt($data, $encrypted, $pi_key);//私钥加密
$encrypted = base64_encode($encrypted);//base64只是为了避免特殊字符
var_dump('私钥加密之后的结果:
' . $encrypted);echo '
';
openssl_public_decrypt(base64_decode($encrypted), $decrypted, $pu_key);//私钥加密的内容通过公钥可用解密出来
var_dump(json_decode($decrypted, true));echo '
';
//公钥加密私钥解密
openssl_public_encrypt($data, $encrypted, $pu_key);//公钥加密
$encrypted = base64_encode($encrypted); //base64只是为了避免特殊字符
var_dump('公钥加密之后的结果:
' . $encrypted);echo '
';
openssl_private_decrypt(base64_decode($encrypted), $decrypted, $pi_key);//私钥解密
var_dump(json_decode($decrypted, true));echo '
';
对于字符串超长的加密,需要另外封装:
/**
* RSA公钥加密
* @param $originalStr
* @return string
*/
function rsaEncrypt($originalStr){
$str = base64_encode($originalStr);
$crypto = '';
$pub_key = openssl_pkey_get_public(RSA_public_key);
foreach (str_split($str, 117) as $chunk) {
openssl_public_encrypt($chunk, $encryptData, $pub_key);
$crypto .= $encryptData;
}
return $crypto;
}
/**
* RSA私钥解密
* @param $encryptStr
* @return bool|string
*/
function rsaDecrypt($encryptStr){
$crypto = '';
$pri_key = openssl_pkey_get_private(RSA_private_key);
foreach (str_split($encryptStr, 128) as $chunk) {
openssl_private_decrypt($chunk, $decryptData, $pri_key);
$crypto .= $decryptData;
}
return base64_decode($crypto);
}