当前位置:   article > 正文

RSA基本介绍、加解密、加验签

rsa

学习目标:

  • 公钥与私钥
  • 加密、解密
  • 加签、验签
  • 使用场景
  • 加密、解密代码
  • 加签、验签代码

学习内容:

提示:前面是一些数据概念的表述,后面会举例,进一步说明和使用;

一、概念

RSA加密是一种非对称加密算法。数据传输过程中不进行秘钥的传递。确保了信息的安全性,避免了直接传递秘钥所造成的被破解的风险。与对称加密算法不同的是,RSA算法有两个不同的密钥,一个是公钥,一个是私钥。

1. 公钥与私钥

公钥:公钥用来给数据加密,用公钥加密的数据只能用私钥解密。
私钥:私钥用来给需要传输的文本的摘要进行加密,获得密文的这个过程也叫做 签名,同理用私钥签名的数据只能用公钥来实现签名验证

2.加密、解密

我们通常所说的加密、解密指的是:公钥加密,私钥解密,加密是为了防止信息被泄漏。

3.加签、验签

通常所说的加签、验签指的是:私钥加签、公钥验签,加签是为了防止信息被篡改。

4.使用场景

网络通信安全、数字签名、身份认证、数据加密等。

举例场景一:聊天

RSA加密的过程
(1)A 生成了一对密钥(公钥和私钥),私钥不公开自己留着,公钥公开 ,发送给所有想发送的人。
(2)A 传递公钥给 B,B用A的公钥,对信息加密,发送给A
(3)A 接收到 B,发送的信息,用A的私钥,解密信息,获取数据。
这个过程,有两次传递,一次是A将公钥传给B,第二次是B将公钥加密后的信息传给A,即使两次均被恶意获取,也没有关系,只有A手中的私钥,可以解密出准确的信息。

场景二:A收到B的信息后,需要回复“收到”,形成闭环

RSA签名的过程:
(1)A 生成了一对密钥(公钥和私钥),私钥不公开自己留着,公钥公开 ,所有人可以获取。
(2)A用私钥将要发送的信息进行加签,形成签名,发送给B。
(3)B接收到A发送的信息,获取A的公钥进行验签,如果验签失败证明消息被篡改。

这个过程中也有2次传递,第一次A将私钥加密的信息传递给B,第二次 B 获取 A 的公钥,即使被恶意截获,也没有危险,即使知道了消息的内容,也无法伪造带签名的信息回复给B,因为只有A的私钥才能对信息进行签名,防止了信息被恶意篡改。

但是,综合上边两个场景你会发现,第一个场景虽然被截获但并没有泄漏,但是可以利用截获的公钥,加密假的指令,然后传递给A。第二个场景虽然截获的消息不能被篡改,但是消息的内容,可以利用公钥来获得,并不能防止泄漏。所以在实际应用中,要根据情况使用,也可以同时使用加密和签名,
比如A和B都有一套自己的公钥和秘钥,当 A 要给B发送消息时,先用 B 的 公钥对消息加密,再用A的私钥对消息签名。B在拿到消息后,先用A的公钥对消息验签,确认数据没有被恶意篡改。再用B的私钥,对消息解密获得最终信息。达到既不泄露也不篡改,更能保证信息的安全性。
在这里插入图片描述

RSA加解密、签名验签的代码

rsa双向加密

相关函数

openssl_public_encrypt() 公钥加密 => openssl_private_decrypt() 私钥解密
openssl_private_encrypt() 私钥加密 => openssl_public_decrypt() 公钥解密
openssl_sign() 私钥加签 => openssl_verify() 公钥验签

加密与解密

openssl_public_encrypt() 公钥加密 => openssl_private_decrypt() 私钥解密

<?php
	 /**
     * 公钥加密
     * @param $data 需要加密数据
     * @return string|null
     *
     */
     define('BAOFOO_ENCRYPT_LEN',50);
    public function pubEncrypt($data){

        if(!is_string($data)){
            return null;
        }
        $data = json_encode($data,320);
        $encryptdata= "";
        $totalLen = strlen($data);
        $encryptPos = 0;
        while($encryptPos < $totalLen){
            openssl_public_encrypt(substr($data,$encryptPos,BAOFOO_ENCRYPT_LEN),$encrypted,$publickey);
            $encryptdata .= base64_encode($encrypted).',';
            $encryptPos += BAOFOO_ENCRYPT_LEN;
        }
        if($encryptdata){
            return $encryptdata;
        }
        return null;
    }
	/**
     * 秘钥解密
     * @param $encrypted   需要解密数据
     * @return mixed|null
     */
    public function privDecrypt($encrypted){
        if(!is_string($encrypted)){
            return null;
        }
        $crypto = '';
        $crypted = explode(',',substr($encrypted,0,-1));
        foreach($crypted as $chunk){
            openssl_private_decrypt(base64_decode($chunk),$decrypted,$privatekey);
            $crypto .= $decrypted;
        }
        return $crypto;
    }


?>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

openssl_private_encrypt() 私钥加密 => openssl_public_decrypt() 公钥解密同上不做过多赘述。

注意:RSA加密中必须考虑到密码长度、明文长度和密文长度问题。明文长度需要小于私钥长度 。而密文长度则等于密钥长度。因此当加密内容长度大于密钥长度时,有效的rsa加解密就需要对内容进行分段。
所以如果要对任意长度的数据进行加密,就需要将数据分段进行注意加密,并将结果进行拼接。同样,解码也需要分段解码,并将结果进行拼接。

签名与验签
<?php
 /**
     * 私钥加签
     * @param $data  需要加签的数据
     * @return string|null
     */
    public function sign($data){
        $data = json_encode($data,320);
        $signdata = "";
        $totalLen =strlen($data);
        $signPos = 0;
        while($signPos <$totalLen){
            openssl_sign(substr($data,$signPos,BAOFOO_ENCRYPT_LEN),$sign,$this->privatekey);
            $signdata .= base64_encode($sign).',';
            $signPos += BAOFOO_ENCRYPT_LEN;
        }
        return $signdata;

    }

    /**
     * 公钥验证
     * @param $data	源数据/hash算法后的值
     * @param $sign	签名
     * @return bool|null
     */
    public function verify($data,$sign){
        $signdata = explode(',',substr($sign,0,-1));
        $data = json_encode($data,320);
        $signPos = 0;
        $res = '';
        foreach($signdata as $chunk){
            $res = (bool)openssl_verify(substr($data,$signPos,BAOFOO_ENCRYPT_LEN),base64_decode($chunk),$this->publickey);
            if(!$res){
				return null;
			}
            $signPos += BAOFOO_ENCRYPT_LEN;
        }
        return $res;

    }
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/446972
推荐阅读
相关标签
  

闽ICP备14008679号