RSA+PHP 非对称加密解密

生成密钥

# 生成私钥文件
openssl genrsa -out rsa_private_key.pem 1024
# 生成公钥文件
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
# 生成私钥文件 two
openssl genrsa -out rsa_private_key_two.pem 1024
# 生成公钥文件 two
openssl rsa -in rsa_private_key_two.pem -pubout -out rsa_public_key_two.pem

业务场景

为了安全起见采用
(服务端:rsa_public_key_two 加密,rsa_private_key 解密,客户端:rsa_private_key_two 解密,rsa_public_key 解密)
双秘钥进行加密解密,如果实行不通可以多次试验。

实际上

S(two 公钥加密,one 私钥解密)
C(two 私钥解密,one 公钥加密)
// 当然还有其他的加密解密方法,我这里略过...

PHP 服务端

// 先配置一下证书,可以在config.php 追加或在 extra 目录新建一个 rsa.php 配置文件,视个人情况而定。
    'rsa' => [
        // 秘钥 one
        'private_key' => file_get_contents(ROOT_PATH. 'rsa_private_key.pem'),
        'public_key' => file_get_contents(ROOT_PATH. 'rsa_public_key.pem'),
        // 秘钥 two
        'private_key_two' => file_get_contents(ROOT_PATH. 'rsa_private_key_two.pem'),
        'public_key_two' => file_get_contents(ROOT_PATH. 'rsa_public_key_two.pem'),
    ]
// 加密函数使用到了 OpenSSL 扩展,在服务端需要先安装并开启 OpenSSL 扩展,默认使用的是 PKCS1 填充模式。
/**
 * @Author(作者): YALE
 * @DateTime(开发创建时间): 2022/3/1
 * @LastTime(最后修改时间): 2022/3/1
 * @param $str
 * @Return(返回值): string
 * @FunctionName(方法名称): encryptData
 * @Remarks(备注): RSA 加密
 */
function encryptData($str) {
    $result = '';
    $chunks = str_split($str, 117);
    foreach ($chunks as $value) {
        openssl_public_encrypt($value, $crypted, config('rsa.public_key_two'));
        $result .= base64_encode($crypted);
    }
    return $result;
}
/**
 * @Author(作者): YALE
 * @DateTime(开发创建时间): 2022/3/1
 * @LastTime(最后修改时间): 2022/3/1
 * @param $data
 * @Return(返回值): string
 * @FunctionName(方法名称): decryptData
 * @Remarks(备注): RSA 解密
 */
function decryptData($data) {
    $result = '';
    $chunks = str_split($data, 172);
    foreach ($chunks as $value) {
        openssl_private_decrypt(base64_decode($value), $decrypted, config('rsa.private_key'));
        $result .= $decrypted;
    }
    return $result;
}

通用:jsencrypt

微信客户端

// 根据情况使用 全局引入 或 局部引入
import JSEncrypt from '@/static/jsencrypt';
// 示例为全局引入,配置 main.js
Vue.prototype.jsencrypt = new JSEncrypt();
// 公钥解密
Vue.prototype.public_key = `-----BEGIN PUBLIC KEY-----
    ********************************************
-----END PUBLIC KEY-----`;
// 私钥加密
Vue.prototype.private_key = `-----BEGIN RSA PRIVATE KEY-----
    ********************************************
-----END RSA PRIVATE KEY-----`;

// 加密解密方法
// 设置公钥
this.jsencrypt.setPublicKey(this.public_key);
// 加密
var string = this.jsencrypt.encryptLong(JSON.stringify({name:'yale', age: 18})) 
console.log(string);
// 设置私钥
this.jsencrypt.setPrivateKey(this.private_key);
// 解密
console.log(this.jsencrypt.decryptLong(string));

浏览器客户端

<script src="/***/jsencrypt.js"></script>
<script type="text/javascript">
    $(function() {
        var rsa_public_key = `-----BEGIN PUBLIC KEY-----
    ********************************************
-----END PUBLIC KEY-----`;
        var rsa_private_key = `-----BEGIN RSA PRIVATE KEY-----
    ********************************************
-----END RSA PRIVATE KEY-----`;
        // rsa 加密
	function encrypt(data)
        {
            var encrypt = new JSEncrypt();
            encrypt.setPublicKey(rsa_public_key);
            var encrypted = encrypt.encrypt(data);
            return encrypted;
        }
        // rsa 解密
        function decrypt(encrypted)
	{
            var decrypt = new JSEncrypt();
            decrypt.setPrivateKey(rsa_private_key);
            var uncrypted = decrypt.decrypt(encrypted);
            return uncrypted;
        }
            
	var encrypted = encrypt(JSON.stringify({name:'yale', age: 18}));
	console.log(encrypted);
        var uncrypted = decrypt(encrypted);
    });
</script>

由于使用的是双秘钥的方式所以客户端不能自己加密解密
其他平台暂时没有涉及到,遇到后再补充了

posted @ 2022-03-01 21:00  孤陌  阅读(281)  评论(0编辑  收藏  举报