zoukankan      html  css  js  c++  java
  • 【PHP】RSA 长字符串 分段加密(117)解密(128)

    Q1:为什么RSA对长字符串需分段进行加、解密?

    RSA对明文长度和密文长度有限制,如果要加密的明文太长则会出错。RSA 1024bit 加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。

    Q2:解决办法?
    RSA密钥长度1024bit,加密的时候117个字符加密一次,然后把所有的密文拼接成一个密文;解密的时候需要128个字符解密一下,然后拼接成数据。

    Q3:RSA不同的密钥长度,在分段加、解密时,分段字节数是不同的
    若RSA密钥长度为M bit,分段加密字节数为(M/8-11),分段解密字节数为(M/8)。

    如:
    1024bit:分段加密字节数为117,分段解密字节数为128。
    2048bit:分段加密字节数为245,分段解密字节数为256。

    Demo 1:

    private $private_key = "-----BEGIN RSA PRIVATE KEY-----
    MIICXAIBAAKBgQDvluFNiF8IrIsddK0OXBAvVBJH11OKvy9er1tRGn9yEJoHCJY3
    EU/xz2LasCK8AwgRIqGJbvDBgRa70c3QT9j+wPqNqqJCSoSEKifnDUk1RgUReJT6
    iqWaJyfM+WM3aHnKl61RZL4NV5qKe4CHMtaH/JtBCC/JzpuFER1P1IhCtQIDAQAB
    AoGAaFYQb68/k4twWbeB1YsKEVJPU7HV08pGWrmKztr3PTk1mnKG2BxV8DwcFJg3
    yCCZ1rx6FFuXxOzudYR8WIctO4wdsEbFky/cEGsfc6JJjiktmZaQ7MvobGNwnoFJ
    QvRxDd+5uD87JE19iBSgUpLVtXbv+pZxSpD70vitnMdSctECQQD66Z5HsuC8DUPu
    OLQHNN4ra5Op179Xlq7LiEFW4GaVgonw24kiLX23c7CK7295Rgxct1fwQKyuU9br
    n2uj8toDAkEA9HJ85BWlm2OfUm6VI3Q99rjlpCnhRyz70+sEtf7if1SpctVxNTkX
    UOnXlpPTohjAHNhzh9fa1hh/ySH9sRMu5wJAa//8uh3br/YBxFsx2lw+OPBQGe4c
    lSXtzPu0LCHg5f/PQhYs28I696jbV6IiGFA3Z/0e4/HiohLCUp9HJMWWYwJACE53
    pfyCUyRwfomZccn6bQ7dZtWxfQyvRgU/dLvDkJYc5/UO0sMs4qf/lnNRhrmWlaRZ
    UK1qF0pf1ULdbw360wJBAObrYopW2kvIlE09j9SEgNtgVsmfZlf85c4EAZrFJP/T
    8nMNKQGo92Gd3HvbjJ+ZBOP1IFt+FDAsXeSLWLAwJrg=
    -----END RSA PRIVATE KEY-----";
    
    private $public_key = "-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvluFNiF8IrIsddK0OXBAvVBJH
    11OKvy9er1tRGn9yEJoHCJY3EU/xz2LasCK8AwgRIqGJbvDBgRa70c3QT9j+wPqN
    qqJCSoSEKifnDUk1RgUReJT6iqWaJyfM+WM3aHnKl61RZL4NV5qKe4CHMtaH/JtB
    CC/JzpuFER1P1IhCtQIDAQAB
    -----END PUBLIC KEY-----
    ";
    
    public function rsa(){
    
    	$content = "这是一段文字";
    	$res = $this->superLongPublicKeyEncrypt($content,$this->public_key,false,true);
    	var_dump($res);
    	$content = "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";
    	$res = $this->superLongPrivateKeyDecrypt($content,$this->private_key,false,true);
    	var_dump($res);
    }
    
    public function superLongPublicKeyEncrypt($content, $rsaPublicKey, $choicePath = true, $withBase64 = false)
    {
    	if ($choicePath) {
    		$pubKeyId = openssl_pkey_get_public($rsaPublicKey);//绝对路径读取
    	} else {
    		$pubKeyId = $rsaPublicKey;//公钥
    	}
    
    	$RSA_ENCRYPT_BLOCK_SIZE = 117;
    
    	$result = '';
    	$data = str_split($content, $RSA_ENCRYPT_BLOCK_SIZE);
    	foreach ($data as $block) {
    		openssl_public_encrypt($block, $dataEncrypt, $pubKeyId, OPENSSL_PKCS1_PADDING);
    		$result .= $dataEncrypt;
    	}
    
    	if ($withBase64) {
    		return base64_encode($result);
    	} else {
    		return $result;
    	}
    }
    
    public static function superLongPrivateKeyDecrypt($content, $rsaPrivateKey, $choicePath = true, $withBase64 = false)
    {
    	if ($choicePath) {
    		$priKeyId = openssl_pkey_get_private($rsaPrivateKey);//绝对路径
    	} else {
    		$priKeyId = $rsaPrivateKey;//私钥
    	}
    
    	if ($withBase64) {
    		$data = base64_decode($content);
    	}
    
    	$RSA_DECRYPT_BLOCK_SIZE = 128;
    
    	$result = '';
    	$data = str_split($data, $RSA_DECRYPT_BLOCK_SIZE);
    	foreach ($data as $block) {
    		openssl_private_decrypt($block, $dataDecrypt, $priKeyId, OPENSSL_PKCS1_PADDING);
    		$result .= $dataDecrypt;
    	}
    
    	if ($result) {
    		return $result;
    	} else {
    		return false;
    	}
    }
    

    Demo 2:

    <?php
    
    /**
     * PHP实现RSA分段加密、解密
     *
     * Class RSA
     */
    class RSA
    {
        public $privateKey = './rsa_private_key.pem';           //私钥地址
        public $publicKey = './rsa_public_key.pem';             //公钥地址
    
        public $pri_key = '-----BEGIN RSA PRIVATE KEY-----
    MIICXAIBAAKBgQDvluFNiF8IrIsddK0OXBAvVBJH11OKvy9er1tRGn9yEJoHCJY3
    EU/xz2LasCK8AwgRIqGJbvDBgRa70c3QT9j+wPqNqqJCSoSEKifnDUk1RgUReJT6
    iqWaJyfM+WM3aHnKl61RZL4NV5qKe4CHMtaH/JtBCC/JzpuFER1P1IhCtQIDAQAB
    AoGAaFYQb68/k4twWbeB1YsKEVJPU7HV08pGWrmKztr3PTk1mnKG2BxV8DwcFJg3
    yCCZ1rx6FFuXxOzudYR8WIctO4wdsEbFky/cEGsfc6JJjiktmZaQ7MvobGNwnoFJ
    QvRxDd+5uD87JE19iBSgUpLVtXbv+pZxSpD70vitnMdSctECQQD66Z5HsuC8DUPu
    OLQHNN4ra5Op179Xlq7LiEFW4GaVgonw24kiLX23c7CK7295Rgxct1fwQKyuU9br
    n2uj8toDAkEA9HJ85BWlm2OfUm6VI3Q99rjlpCnhRyz70+sEtf7if1SpctVxNTkX
    UOnXlpPTohjAHNhzh9fa1hh/ySH9sRMu5wJAa//8uh3br/YBxFsx2lw+OPBQGe4c
    lSXtzPu0LCHg5f/PQhYs28I696jbV6IiGFA3Z/0e4/HiohLCUp9HJMWWYwJACE53
    pfyCUyRwfomZccn6bQ7dZtWxfQyvRgU/dLvDkJYc5/UO0sMs4qf/lnNRhrmWlaRZ
    UK1qF0pf1ULdbw360wJBAObrYopW2kvIlE09j9SEgNtgVsmfZlf85c4EAZrFJP/T
    8nMNKQGo92Gd3HvbjJ+ZBOP1IFt+FDAsXeSLWLAwJrg=
    -----END RSA PRIVATE KEY-----';
        public $pub_key = '-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvluFNiF8IrIsddK0OXBAvVBJH
    11OKvy9er1tRGn9yEJoHCJY3EU/xz2LasCK8AwgRIqGJbvDBgRa70c3QT9j+wPqN
    qqJCSoSEKifnDUk1RgUReJT6iqWaJyfM+WM3aHnKl61RZL4NV5qKe4CHMtaH/JtB
    CC/JzpuFER1P1IhCtQIDAQAB
    -----END PUBLIC KEY-----';
    
        /**
         * RSA constructor.
         * @param null $publicKeyPath
         * @param null $privateKeyPath
         * @param null $publicKey
         * @param null $privateKey
         * @throws FileNotFoundException
         */
        public function __construct($publicKeyPath=null, $privateKeyPath=null, $publicKey=null, $privateKey=null) {
    
            if ($this->checkKeyFile($publicKeyPath)) {
                $this->pub_key = openssl_pkey_get_public(file_get_contents($publicKeyPath));
            }
    
            if ($this->checkKeyFile($privateKeyPath)) {
                $this->pri_key = openssl_pkey_get_private(file_get_contents($privateKeyPath));
            }
    
            if (!is_null($publicKey)) {
                $this->pub_key = openssl_pkey_get_public($this->formatterPublicKey($publicKey));
            }
    
            if (!is_null($privateKey)) {
                $this->pri_key = openssl_pkey_get_private($this->formatterPrivateKey($privateKey));
            }
    
        }
    
        /**
         * 校验文件是否存在
         * @param $keyPath string 文件路径
         * @return bool
         * @throws FileNotFoundException
         */
        public function checkKeyFile($keyPath)
        {
            if (!is_null($keyPath)) {
                if(!file_exists($keyPath)) {
                    throw new FileNotFoundException($keyPath);
                }
    
                return true;
            }
    
            return false;
        }
    
        /**
         * 格式化公钥
         * @param $publicKey string 公钥
         * @return string
         */
        public function formatterPublicKey($publicKey)
        {
            if (str_contains('-----BEGIN PUBLIC KEY-----', $publicKey)) return $publicKey;
    
            $str = chunk_split($publicKey, 64, PHP_EOL);//在每一个64字符后加一个
    
            $publicKey = "-----BEGIN PUBLIC KEY-----".PHP_EOL.$str."-----END PUBLIC KEY-----";
    
            return $publicKey;
        }
    
        /**
         * 格式化私钥
         * @param $privateKey string 公钥
         * @return string
         */
        public function formatterPrivateKey($privateKey)
        {
            if (str_contains('-----BEGIN RSA PRIVATE KEY-----', $privateKey)) return $privateKey;
    
            $str = chunk_split($privateKey, 64, PHP_EOL);//在每一个64字符后加一个
    
            $privateKey = "-----BEGIN RSA PRIVATE KEY-----".PHP_EOL.$str."-----END RSA PRIVATE KEY-----";
    
            return $privateKey;
        }
    
        /**
         *  公钥加密(分段加密)
         *  emptyStr    需要加密字符串
         */
        public function encrypt($str) {
            $crypted = array();
            $data = $str;
            $dataArray = str_split($data, 117);
            foreach($dataArray as $subData){
                $subCrypted = null;
                openssl_public_encrypt($subData, $subCrypted, $this->pub_key);
                $crypted[] = $subCrypted;
            }
            $crypted = implode('',$crypted);
            return base64_encode($crypted);
        }
    
        /**
         *  私钥解密(分段解密)
         *  @encrypstr  加密字符串
         */
        public function decrypt($encryptstr) {
            $encryptstr = base64_decode($encryptstr);
            $decrypted = array();
            $dataArray = str_split($encryptstr, 128);
    
            foreach($dataArray as $subData){
                $subDecrypted = null;
                openssl_private_decrypt($subData, $subDecrypted, $this->pri_key);
                $decrypted[] = $subDecrypted;
            }
            $decrypted = implode('',$decrypted);
            return $decrypted;
        }
    
    }
    
    
    
    $result = new RSA();
    
    $data = '{"phone":"15256416396","name":"张三","inAcctNo":"8239472342342342","idNo":"342422165897654326","inAcctBankName":"平安银行"}';
    
    $dataEn = $result->encrypt($data);
    echo $dataEn;
    
    echo "<pre>";
    $dataDe = $result->decrypt($dataEn);
    echo $dataDe;
    

    参考:
    https://blog.csdn.net/u010144805/article/details/80547370
    https://blog.liuguofeng.com/p/5305
    https://blog.csdn.net/h1101723183/article/details/102489052
    https://blog.csdn.net/draven1122/article/details/55212252/

  • 相关阅读:
    封装Socket.BeginReceive/EndReceive以支持Timeout
    使用反射动态创建类型实例
    泛型List<T>排序(利用反射)
    复旦版最佳医院排行 沪21家医院入选全国百佳
    C#格式化字符串
    一些很酷的.Net技巧
    系列文章--SQLite文章
    C#垃圾回收机制
    C#中Cache的使用
    ASP.NET Cache缓存的使用
  • 原文地址:https://www.cnblogs.com/meetuj/p/14954533.html
Copyright © 2011-2022 走看看