php使用openssl进行Rsa长数据加密(117)解密(128)


PHP使用openssl进行Rsa加密,如果要加密的明文太长则会出错,解决方法:加密的时候117个字符加密一次,然后把所有的密文拼接成一个密文;解密的时候需要128个字符解密一下,然后拼接成数据。

加密:

    /**
     * 加密
     * @param $originalData
     * @return string|void
     */
    /*function encrypt($originalData){

        // if (openssl_private_encrypt($originalData, $encryptData, $this->rsaPrivateKey)) {
        if (openssl_public_encrypt($originalData, $encryptData, $this->rsaPublicKey)) {
            return base64_encode($encryptData);
        } else {
            return false;
        }
    }*/
    function encrypt($originalData){

        $crypto = '';

        foreach (str_split($originalData, 117) as $chunk) {

            openssl_public_encrypt($chunk, $encryptData, $this->rsaPublicKey);

            $crypto .= $encryptData;
        }

        return base64_encode($crypto);
    }

解密:

    /**
     * 私钥解密
     * @param $encryptData
     */

    /*function decrypt($encryptData){

        // if (openssl_public_decrypt(base64_decode($encryptData), $decryptData, $this->rsaPublicKey)) {
        if (openssl_private_decrypt(base64_decode($encryptData), $decryptData, $this->rsaPrivateKey)) {

            return $decryptData;

        } else {

            return false;
        }
    }*/
    function decrypt($encryptData){

        $crypto = '';

        foreach (str_split(base64_decode($encryptData), 128) as $chunk) {

            openssl_private_decrypt($chunk, $decryptData, $this->rsaPrivateKey);

            $crypto .= $decryptData;
        }

        return $crypto;
    }

也可以使用如下方法:
加密:

    function encrypt($data, $rsa_publickey){
        $split = str_split($data, 117);  // 1024 bit && OPENSSL_PKCS1_PADDING 不大于117即可
        $crypto = '';
        foreach ($split as $chunk) {
            $isOkay = openssl_public_encrypt($chunk, $encryptData, $rsa_publickey);
            if(!$isOkay){
                return false;
            }
            $crypto .= base64_encode($encryptData);
        }
        return $crypto;
    }

解密:

    function decrypt($data, $rsa_privatekey){
        $split = str_split($data, 172);  // 1024 bit 固定172
        $crypto = '';
        foreach ($split as $chunk) {
            $isOkay = openssl_private_decrypt(base64_decode($chunk), $decryptData, $rsa_privatekey);  // base64在这里使用,因为172字节是一组,是encode来的
            if(!$isOkay){
                return false;
            }
            $crypto .= $decryptData;
        }
        return $crypto;
    }

借用网上查到的一段比较详细的解释:

RSA加密解密有个填充方式padding的参数,不同编程语言之间交互,需要注意这个。

padding can be one of OPENSSL_PKCS1_PADDING, OPENSSL_SSLV23_PADDING, OPENSSL_PKCS1_OAEP_PADDING,OPENSSL_NO_PADDING



值得注意的是,如果选择密钥是1024bit长的(openssl genrsa -out rsa_private_key.pem 1024),那么支持加密的明文长度字节最多只能是1024/8=128byte;

如果加密的padding填充方式选择的是OPENSSL_PKCS1_PADDING(这个要占用11个字节),那么明文长度最多只能就是128-11=117字节。如果超出,那么这些openssl加解密函数会返回false。



这时有个解决办法,把需要加密的源字符串按少于117个长度分开为几组,在解密的时候以172个字节分为几组。

其中的『少于117』(只要不大于117即可)和『172』两个数字是怎么来的,值得一说。

为什么少于117就行,因为rsa encrypt后的字节长度是固定的,就是密钥长1024bit/8=128byte。因此只要encrypt不返回false,即只要不大于117个字节,那么返回加密后的都是128byte。

172是因为什么?因为128个字节base64_encode后的长度固定是172。

这里顺便普及下base64_encode。encode的长度是和原文长度有个计算公式:

$len2 = $len1%3 >0 ? (floor($len1/3)*4 + 4) : ($len1*4/3);

参考:
https://www.cnblogs.com/firstForEver/p/5803940.html
https://www.cnblogs.com/CraryPrimitiveMan/p/6242167.html?utm_source=itdadao&utm_medium=referral

Author:leedaning
本文地址:http://blog.csdn.net/leedaning/article/details/51780511

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告