PHP实现RSA与RSA256加密,解密,加签,验签

Posted Morven

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP实现RSA与RSA256加密,解密,加签,验签相关的知识,希望对你有一定的参考价值。

1、RSA加密简介

  RSA加密是一种非对称加密。可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。是由一对密钥来进行加解密的过程,分别称为公钥和私钥,两者之间有数学相关,该加密算法的原理就是对一极大整数做因数分解的困难性来保证安全性。通常个人保存私钥,公钥是公开的(可能同时多人持有)。

2、RSA加密、签名区别

  加密和签名都是为了安全性考虑,但略有不同。常有人问加密和签名是用私钥还是公钥?其实都是对加密和签名的作用有所混淆。简单的说,加密是为了防止信息被泄露,而签名是为了防止信息被篡改。这里举2个例子说明。

第一个场景:战场上,B要给A传递一条消息,内容为某一指令。

RSA的加密过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A传递自己的公钥给B,B用A的公钥对消息进行加密。

(3)A接收到B加密的消息,利用A自己的私钥对消息进行解密。

  在这个过程中,只有2次传递过程,第一次是A传递公钥给B,第二次是B传递加密消息给A,即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行解密,防止了消息内容的泄露。

第二个场景:A收到B发的消息后,需要进行回复“收到”。

RSA签名的过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给B。

(3)B收到消息后,在获取A的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是A回复的。

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

  但是,综合两个场景你会发现,第一个场景虽然被截获的消息没有泄露,但是可以利用截获的公钥,将假指令进行加密,然后传递给A。第二个场景虽然截获的消息不能被篡改,但是消息的内容可以利用公钥验签来获得,并不能防止泄露。所以在实际应用中,要根据情况使用,也可以同时使用加密和签名,比如A和B都有一套自己的公钥和私钥,当A要给B发送消息时,先用B的公钥对消息加密,再对加密的消息使用A的私钥加签名,达到既不泄露也不被篡改,更能保证消息的安全性。

  总结:公钥加密、私钥解密、私钥签名、公钥验签。

rsa 类

class Rsa

    /**
     * private key
     */
    private $_privKey;

    /**
     * public key
     */
    private $_pubKey;

    /**
     * the keys saving path
     */
    private $_keyPath;

    public function __construct ($path)

        if (empty($path) || !is_dir($path)) 
            throw new \\Exception('Must set the keys save path');
        
        //设置私钥
        $this->_keyPath = $path;
        $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'rsa_private_key.pem';
        $prk = file_get_contents($file);
        $this->_privKey = openssl_pkey_get_private($prk);
        //设置公钥
        $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'rsa_public_key.pem';
        $puk = file_get_contents($file);
        $this->_pubKey = openssl_pkey_get_public($puk);
    



    /**
     * setup the private key
     */
    public function setupPrivKey ()

        if (is_resource($this->_privKey)) 
            return true;
        
        $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'rsa_private_key.pem';
        $prk = file_get_contents($file);
        $this->_privKey = openssl_pkey_get_private($prk);
        return true;
    

    /**
     * setup the public key
     */
    public function setupPubKey ()

        if (is_resource($this->_pubKey)) 
            return true;
        
        $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'rsa_public_key.pem';
        $puk = file_get_contents($file);
        $this->_pubKey = openssl_pkey_get_public($puk);
        return true;
    

    /**
     * @function 私钥加密
     * @param $data
     * @return string|null
     */
    public function privEncrypt ($data)

        if (!is_string($data)) 
            return null;
        

        $r = openssl_private_encrypt($data, $encrypted, $this->_privKey);
        if ($r) 
            return base64_encode($encrypted);
        
        return null;
    

    /**
     * @function 私钥解密
     * @param $data
     * @return string|null
     */
    public function privDecrypt ($encrypted)

        if (!is_string($encrypted)) 
            return null;
        
        $encrypted = base64_decode($encrypted);
        $r = openssl_private_decrypt($encrypted, $decrypted, $this->_privKey);
        if ($r) 
            return $decrypted;
        
        return null;
    

    /**
     * @function 公钥加密
     * @param $data
     * @return string|null
     */
    public function pubEncrypt ($data)

        if (!is_string($data)) 
            return null;
        
        $r = openssl_public_encrypt($data, $encrypted, $this->_pubKey);
        if ($r) 
            return base64_encode($encrypted);
        
        return null;
    

    /**
     * @function 公钥解密
     * @param $data
     * @return string|null
     */
    public function pubDecrypt ($crypted)

        if (!is_string($crypted)) 
            return null;
        
        $crypted = base64_decode($crypted);
        
        $r = openssl_public_decrypt($crypted, $decrypted, $this->_pubKey);
        if ($r) 
            return $decrypted;
        
        return null;
    

    /**
     * @function 私钥加签
     * @param $data
     * @return string|null
     */
    public function sign ($data)

        if (!is_string($data)) 
            return null;
        
        openssl_sign($data, $sign, $this->_privKey);
        //base64编码
        $sign = base64_encode($sign);
        return $sign;
    

    /**
     * @function 公钥验签
     * @param $data
     * @return string|null
     */
    public function verify($data, $sign)
        if (!is_string($data)) 
            return null;
        
        $result = (bool)openssl_verify($data, base64_decode($sign), $this->_pubKey);
        return $result;
    


    public function __destruct ()

        empty($this->_privKey) ? '' : openssl_free_key($this->_privKey);
        empty($this->_pubKey) ? '' : openssl_free_key($this->_pubKey);
    

使用例子:

class Index

    public function index()

        $RSA = new Rsa(config('key_path'));

        //对数据公钥加密及私钥解密
        $string = 'test';

        $pubString = $RSA->pubEncrypt($string);
        echo '用公钥加密后数据:'.$pubString .'<br/>';

        $priDeString = $RSA->privDecrypt($pubString);
        echo '用私钥解密数据:'.$priDeString .'<br/>';

        //实现对数据私钥加签及公钥验签

        $sign = $RSA->sign($string);
        echo '用私钥加签后得到签名:'.$sign .'<br/>';
        $result = $RSA->verify($string,$sign);
        echo '验证签名是否正确:<br/>';
        dump($result);
    
   

SHA256WithRSA签名验签&加密解密

加密:

public function RsaEncrypt($str,$pri_key)

        $pi_key =openssl_pkey_get_private($pri_key);

        if(!$pi_key)return false;//秘钥不可用

       openssl_private_encrypt($str,$encrypted,$pi_key);

       $encrypted =base64_encode($encrypted);

       return $encrypted;





解密:
public function RsaDecrypt($str,$pub_key)

        $pu_key =openssl_pkey_get_public($pub_key);

        if(!$pu_key)return false;//秘钥不可用

        openssl_public_decrypt(base64_decode($str),$decrypted,$pu_key);

        return $decrypted;




使用:

$pri_key ="";

$pub_key = "";

$char = '要加密的字符';//要加密的字符

$sign = $this->RsaEncrypt($char,$pri_key);//加密结果

$result = $this->RsaDecrypt($sign,$pub_key);//对加密结果进行解密

最后一个是支持两种都可以的类

<?php

//rsa和rsa2 PHP版签名生成以及验证类
//$content,$signature,$publicKey,$type,$content原文,$signature被验证的签名,$publicKey和$privateKey公私钥都是只有内容的一行字符串,$type为rsa,或者rsa2
class RSA
	public static function sign($content,$privateKey,$type)
		if($type == "rsa")
			openssl_sign($content,$signature,"-----BEGIN PRIVATE KEY-----\\n".$privateKey."\\n-----END PRIVATE KEY-----", OPENSSL_ALGO_SHA1);
		elseif ($type == "rsa2") 
			openssl_sign($content,$signature,"-----BEGIN PRIVATE KEY-----\\n".$privateKey."\\n-----END PRIVATE KEY-----", OPENSSL_ALGO_SHA256);
		else
			throw new Exception("Only support OPENSSL_ALGO_SHA1 or OPENSSL_ALGO_SHA256 algorithm signature!");
		
		return base64_encode($signature);
	

	public static function verify($content,$signature,$publicKey,$type)
		if($type == "rsa")
			return openssl_verify($content,base64_decode($signature),"-----BEGIN PUBLIC KEY-----\\n".$publicKey."\\n-----END PUBLIC KEY-----", OPENSSL_ALGO_SHA1);
		elseif ($type == "rsa2") 
			return openssl_verify($content,base64_decode($signature),"-----BEGIN PUBLIC KEY-----\\n".$publicKey."\\n-----END PUBLIC KEY-----", OPENSSL_ALGO_SHA256);
		else
			throw new Exception("Only support OPENSSL_ALGO_SHA1 or OPENSSL_ALGO_SHA256 algorithm signature verify!");
		
	

?>

以上是关于PHP实现RSA与RSA256加密,解密,加签,验签的主要内容,如果未能解决你的问题,请参考以下文章

PHP实现RSA与RSA256加密,解密,加签,验签

RSA加密解密及RSA加签验签

RSA公钥加密,私钥解密,私钥加签,公钥验签

iOS小技能:RSA签名验签加密解密的原理

iOS加密:RSA

小程序RSA加密、解密、加签、验签