您的位置:首页 - 教程 - PHP - 正文
PHP的学习--RSA加密解密

PHP服务端与客户端交互或者提供开放API时,通常需要对敏感的数据进行加密,这时候rsa非对称加密就能派上用处了。

举个通俗易懂的例子,假设我们再登录一个网站,发送账号和密码,请求被拦截了。

  • 密码没加密,那攻击者就直接拿到了密码,这是最搓的。
  • 密码加密了,是不可逆加密,那攻击者只需要模拟那个请求即可登录。
  • 密码加密了,是可逆加密,其中携带有时间等参数,后台可以根据时间等参数来判断是否有效,但因为是在前端加密,其加密方式也能在代码中找到,找到加密方式就可以得出解密方式。

但是如果我们使用非对称加密就可以避免以上问题。

非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。

工作过程如下,甲乙之间使用非对称加密的方式完成了重要信息的安全传输。

非对称加密工作过程简要示意图

  • 乙方生成一对密钥(公钥和私钥)并将公钥向其它方公开。
  • 得到该公钥的甲方使用该密钥对机密信息进行加密后再发送给乙方。
  • 乙方再用自己保存的另一把专用密钥(私钥)对加密后的信息进行解密。乙方只能用其专用密钥(私钥)解密由对应的公钥加密后的信息。

在传输过程中,即使攻击者截获了传输的密文,并得到了乙的公钥,也无法破解密文,因为只有乙的私钥才能解密密文。
同样,如果乙要回复加密信息给甲,那么需要甲先公布甲的公钥给乙用于加密,甲自己保存甲的私钥用于解密。

在非对称加密中使用的主要算法有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。

下面我们通过一个例子来说明如何用PHP来实现RSA的加密解密。

<?php
class Rsa
{
    public $privateKey = '';

    public $publicKey = '';
    
    public function __construct()
    {
        $resource = openssl_pkey_new();
        openssl_pkey_export($resource, $this->privateKey);
        $detail = openssl_pkey_get_details($resource);
        $this->publicKey = $detail['key'];
    }

    public function publicEncrypt($data, $publicKey)
    {
        openssl_public_encrypt($data, $encrypted, $publicKey);
        return $encrypted;
    }

    public function publicDecrypt($data, $publicKey)
    {
        openssl_public_decrypt($data, $decrypted, $publicKey);
        return $decrypted;
    }

    public function privateEncrypt($data, $privateKey)
    {
        openssl_private_encrypt($data, $encrypted, $privateKey);
        return $encrypted;
    }

    public function privateDecrypt($data, $privateKey)
    {
        openssl_private_decrypt($data, $decrypted, $privateKey);
        return $decrypted;
    }
}


$rsa = new Rsa();
echo "公钥加密:\n", $rsa->publicKey, "\n";
echo "私钥加密:\n", $rsa->privateKey, "\n";

// 使用公钥加密
$str = $rsa->publicEncrypt('hello', $rsa->publicKey);
// 这里使用base64是为了不出现乱码,默认加密出来的值有乱码
$str = base64_encode($str);
echo "公钥加密(base64处理过):\n", $str, "\n";
$str = base64_decode($str);
$pubstr = $rsa->publicDecrypt($str, $rsa->publicKey);
echo "公钥解密:\n", $pubstr, "\n";
$privstr = $rsa->privateDecrypt($str, $rsa->privateKey);
echo "私钥解密:\n", $privstr, "\n";

// 使用私钥加密
$str = $rsa->privateEncrypt('world', $rsa->privateKey);
// 这里使用base64是为了不出现乱码,默认加密出来的值有乱码
$str = base64_encode($str);
echo "私钥加密(base64处理过):\n", $str, "\n";
$str = base64_decode($str);
$pubstr = $rsa->publicDecrypt($str, $rsa->publicKey);
echo "公钥解密:\n", $pubstr, "\n";
$privstr = $rsa->privateDecrypt($str, $rsa->privateKey);
echo "私钥解密:\n", $privstr, "\n";

大家执行一下可以看到公钥加密的数据,只有私钥能解密,反之亦然,私钥加密的数据只有公钥能解码。

执行结果如下:

这是PHP端的实现,可用在第三方跟平台之间的数据传输,但如果是前端传到后端该怎么办呢,搜索了一下,发现了这个库jsencrypt,但其实现与PHP不太一致。

如果大家需要用到可以参考这篇博客《JS到PHP使用RSA算法进行加密通讯》

参考摘录:

百度百科 非对称加密
PHP文档 加密扩展



评论: