<?php /** * 生成RSA密钥对(公钥和私钥)的命令: * [root@localhost ~]# openssl genrsa -out rsa_private_key.pem 1024 * [root@localhost ~]# openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem * [root@localhost ~]# openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem * 命令①:生成原始RSA私钥文件 * 命令②:将原始RSA私钥文件转换为pkcs8格式 * 命令③:根据原始RSA私钥文件生成RSA公钥文件 * 备 注:公钥发放给客户端用于加密数据,私钥则要留在服务端用于解密客户端发送过来的加密数据。 */ class RSA { private static $publicKeyPath = __DIR__ . '/rsa_public_key.pem'; private static $privateKeyPath = __DIR__ . '/rsa_private_key.pem'; private static $signatureAlgo = OPENSSL_ALGO_SHA512; // 签名算法 /** * (使用公钥)加密 * 备注:相同的数据每次加密产生的密文都是不同的。 * * @param string $data 要加密的数据 * @return string 数据加密后的密文 */ public static function encrypt($data) { $encrypt = ''; // 用于保存密文的变量 // 获取公钥的内容(即字符串) $publicKeyContents = file_get_contents(self::$publicKeyPath); // 获取公钥的资源(获取失败返回FALSE) $publicKeyResource = openssl_pkey_get_public($publicKeyContents); $dataSplit = str_split($data, 117); foreach ($dataSplit as $split) { $splitEncrypt = ''; openssl_public_encrypt($split, $splitEncrypt, $publicKeyResource); // 加密 $encrypt .= $splitEncrypt; } return base64_encode($encrypt); } /** * (使用私钥)解密 * * @param string $data 要解密的数据 * @return string 数据解密后的明文 */ public static function decrypt($data) { $decrypt = ''; // 用于保存明文的变量 // 获取私钥的内容(即字符串) $privateKeyContents = file_get_contents(self::$privateKeyPath); // 获取私钥的资源(获取失败返回FALSE) $privateKeyResource = openssl_pkey_get_private($privateKeyContents); $data = base64_decode($data); $dataSplit = str_split($data, 128); foreach ($dataSplit as $split) { $splitDecrypt = ''; openssl_private_decrypt($split, $splitDecrypt, $privateKeyResource); // 解密 $decrypt .= $splitDecrypt; } return $decrypt; } /** * (使用私钥)生成签名 * 备注:相同的数据每次生成的签名都是相同的。 * * @param string $data 要生成签名的数据 * @return string 签名字符串 */ public static function signature($data) { // 获取私钥的内容(即字符串) $privateKeyContents = file_get_contents(self::$privateKeyPath); // 获取私钥的资源(获取失败返回FALSE) $privateKeyResource = openssl_pkey_get_private($privateKeyContents); $signature = ''; openssl_sign($data, $signature, $privateKeyResource, self::$signatureAlgo); openssl_free_key($privateKeyResource); return base64_encode($signature); } /** * (使用公钥)验证签名 * * @param string $data 数据(必须要和生成签名时的数据一样。PS;签名就是防止伪造数据) * @param string $signature 签名字符串 * @return int 验证结果:1=签名正确,0=签名错误,-1=内部发生错误 */ public static function signatureVerify($data, $signature) { // 获取公钥的内容(即字符串) $publicKeyContents = file_get_contents(self::$publicKeyPath); // 获取公钥的资源(获取失败返回FALSE) $publicKeyResource = openssl_pkey_get_public($publicKeyContents); $signature = base64_decode($signature); $verify = openssl_verify($data, $signature, $publicKeyResource, self::$signatureAlgo); openssl_free_key($publicKeyResource); return $verify; } } $data = 'hello, world'; echo "数据:{$data}" . PHP_EOL; // 数据:hello, world // 备注:由于这里只是简单演示如何使用RSA加解密,故原始数据简单粗暴地使用一串字符串,实际使用中原始数据都是数组格式,开发者需 // 要按照规则将数组转成字符串,通常规则都是将数组进行参数名ASCII字典序排序,然后转成“参数1=参数值1&参数2=参数值2&参数 // 3=参数值3”格式的字符串,然后将字符串进行base64_encode()处理,最后将base64_encode()得出的字符串加密即可,代码如下: // ksort($data); // $dataStr = urldecode(http_build_query($data)); // $dataEncode = base64_encode($dataStr); // $encrypt = RSA::encrypt($dataEncode); // 对原始数据进行加密(备注:相同的数据每次加密产生的密文都是不同的。) $encrypt = RSA::encrypt($data); echo "密文:{$encrypt}" . PHP_EOL; // 密文:A+V00pX0e0kzstPtY+dtgQqJPOx88LUfAdlH66...... // 对密文进行解密 $decrypt = RSA::decrypt($encrypt); echo "明文:{$decrypt}" . PHP_EOL; // 明文:hello, world // 生成签名(备注:相同的数据每次生成的签名都是相同的。) $signature = RSA::signature($data); echo "签名:{$signature}" . PHP_EOL; // 签名:SGYEPOmPVKwBNsbvYwMFbuL0Ybn3G5ipw4wW...... // 验证签名,验证结果:1=签名正确,0=签名错误,-1=内部发生错误 $verify = RSA::signatureVerify($data, $signature); echo "验签:{$verify}" . PHP_EOL; // 验签:1
Copyright © 2023 码农人生. All Rights Reserved