zoukankan      html  css  js  c++  java
  • php RSA加密传输代码示例

      涉及敏感数据的传输,双方最好约定使用加密解密。那RSA非对称加密就大有作为了。

    服务端可以保留自己的私钥,发给客户端对应的公钥。这样就可以互相加解密了。php中rsa加解密实现:

    首先要生成一对公钥私钥。前提是linux机器上安装了openssl命令。

    生成私钥文件:

    openssl genrsa -out rsa_private_key.pem 1024

    利用私钥,生成公钥:

    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

    生成了一对钥匙。php代码:

    <?php
    ini_set('error_reporting', -1);
    ini_set('display_errors', -1);
    
    header('Content-Type: text/html; charset=utf-8');
    
    
    # openssl genrsa -out rsa_private_key.pem 1024
    # openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
    
    
    $private_key = file_get_contents("/home/users/xx/test/rsa_private_key.pem");
    $public_key = file_get_contents("/home/users/xx/test/rsa_public_key.pem");
    
    $pi_key =  openssl_pkey_get_private($private_key);// 可用返回资源id
    $pu_key = openssl_pkey_get_public($public_key);
    
    
    // 加密数据
    $data = array(
        'id' => '1234567890',
        'name' => '小明',
        'mobile' => '123456',
    );
    $data = json_encode($data);
    
    
    $encrypted = '';
    $decrypted = '';
    
    openssl_public_encrypt($data, $encrypted, $pu_key);//公钥加密
    $encrypted = base64_encode($encrypted);// base64传输
    echo $encrypted,"<br/>";
    
    
    openssl_private_decrypt(base64_decode($encrypted), $decrypted, $pi_key);//私钥解密
    echo $decrypted,"<br/>";
    
    
    print_r(json_decode($decrypted, true));

    公钥加密(openssl_public_encrypt),私钥解密(openssl_private_decrypt)。私钥加密(openssl_private_encrypt),公钥解密(openssl_public_decrypt)。都是一个道理,代码类似。

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

    padding can be one of OPENSSL_PKCS1_PADDINGOPENSSL_SSLV23_PADDINGOPENSSL_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);

    明文超出长度的代码(前提是1024bit的密钥长,OPENSSL_PKCS1_PADDING的填充方式,否则数字要变化)

    <?php
    
    
    $pi_key =  openssl_pkey_get_private($private_key);// 资源类型
    $pu_key = openssl_pkey_get_public($public_key);
    
    $data = array(
        'username' => '张三1',
        'mobile' => '13321995977',
        'info' => '14bMitESqD4PYwODWmy7rrrvyFPEnJJTECLjvKB7IkrVxVDkp1XiJnGKH  
    2h5syHQ5qslPSGYJ1M/XkDnGINwaLVHVD3BoKKgKg1bZn7ao5pXT+herqxaVwWs6  
    ga63yVSIC8jcODxiuvxJnUMQRLaqoF6aUb/2VWc2T5MDmxLhAkEA3pwGpvXgLiWL  
    3h7QLYZLrLrbFRuRN4CYl4UYaAKokkAvZly04Glle8ycgOc2DzL4eiL4l/+x/gaq  
    deJU/cHLRQJBANOZY0mEoVkwhU4bScSdnfM6usQowYBEwHYY',
    );
    
    
    $str = json_encode($data);
    
    
    $en = encrypt_rsa($str, $pu_key);
    
    
    $de = decrypt_rsa($en, $pi_key);
    
    echo $de;
    
    
    
    function encrypt_rsa($data, $pu_key){
        $split = str_split($data, 100);// 1024bit && OPENSSL_PKCS1_PADDING  不大于117即可
        foreach ($split as $part) {
            $isOkay = openssl_public_encrypt($part, $en_data, $pu_key);
            if(!$isOkay){
                return false;
            }
            // echo strlen($en_data),'<br/>';
            $encode_data .= base64_encode($en_data);
        }
        return $encode_data;
    }
    
    
    function decrypt_rsa($data, $pi_key){
        $split = str_split($data, 172);// 1024bit  固定172
        foreach ($split as $part) {
            $isOkay = openssl_private_decrypt(base64_decode($part), $de_data, $pi_key);// base64在这里使用,因为172字节是一组,是encode来的
            if(!$isOkay){
                return false;
            }
            $decode_data .= $de_data;
        }
        return $decode_data;
    }

    base64建议参考这篇文章:http://www.ruanyifeng.com/blog/2008/06/base64.html

  • 相关阅读:
    vue-fullcalendar插件
    iframe 父框架调用子框架的函数
    关于调试的一点感想
    hdfs 删除和新增节点
    hadoop yarn 实战错误汇总
    Ganglia 安装 No package 'ck' found
    storm on yarn(CDH5) 部署笔记
    spark on yarn 安装笔记
    storm on yarn安装时 提交到yarn失败 failed
    yarn storm spark
  • 原文地址:https://www.cnblogs.com/firstForEver/p/5803940.html
Copyright © 2011-2022 走看看