暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Php和Java之间RSA加解密实战

程序员升级之路 2021-03-27
1617

一、背景

      最近一项目采用分层架构,前端是Php,后端是Java,一些敏感数据传输采用加密处理,中间调试起来也是非常麻烦,因为每个语言实现的不一样,Php因为语言层面已经封装了,使用起来不用关注太多,但要了解原理就得看C语言写的代码了,反过来Java的实现就繁琐一些,对使用者不太友好,不过相对来说也比较容易了解原理了。


二、生成Key

       linux生成公钥和密钥主要用到的工具是openssl,具体执行过程如下:

    openssl genrsa -out rsa_private_key.pem 1024
    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem
    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
    复制

    第一条命令生成原始 RSA私钥文件 rsa_private_key.pem;

    第二条命令将原始 RSA私钥转换为 pkcs8格式;

    第三条生成RSA公钥 rsa_public_key.pem;


    最后的key大概是这样的:


    三、Php加密

           Php代码比较简单,语言层面已经提供相应函数:

         function rsaEncrypt($rawStr){
          $publicKey = file_get_contents('/data/xxx/app/config/rsa_public_key.pem');
          $key = openssl_pkey_get_public($publicKey);  
          $encrypted = '';
          base64_encode(openssl_public_encrypt($rawStr, $encrypted ,$key));
          return $encrypted;
         }
      复制


      先获取公钥,然后调用openssl_pkey_get_public生成相应格式的公钥,再调用openssl_public_encrypt加密后再用base64加密下,保证出来的结果可读性好一点,不会是二进制字符串。


      四、Java解密

         class RsaDecryptor{
         //根据私钥字符串生成密钥Key 
         public static PrivateKey genBase64PrivateKey(String privateKeyStr) throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr.getBytes()));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        }


          //解密    
          public static String decrypt(String encryptedStr, PrivateKey key){
             Cipher cipher = Cipher.getInstance("RSA/NONE/OAEPPadding");
             cipher.init(2, key);
             return doDecrypt(cipher, Base64.decodeBase64(ciphertext.getBytes()));      
          }
          
          private static String doDecrypt(Cipher cipher, byte[] ciphertext) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int len = ciphertext.length;
        int blockCount = 0;


        for(int offset = 0; len - offset > 0; offset = blockCount * 128) {
        byte[] buffer;
        if(len - offset > 128) {
        buffer = cipher.doFinal(ciphertext, offset, 128);
        } else {
        buffer = cipher.doFinal(ciphertext, offset, len - offset);
        }


        byteArrayOutputStream.write(buffer, 0, buffer.length);
        ++blockCount;
        }


        byte[] decryptedDate = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return new String(decryptedDate);
        }
        }
        复制

        上面是一个工具类,这里只是为了简单使用,所以全部使用了静态函数,具体使用如下:

          String privateKey = "abc";
          PrivateKey key = RsaDecryptor.genBase64PrivateKey(privateKey);
          RsaDecryptor.decrypt("加密字符串", key);
          复制

          即先拿到私钥,再进行解密。


          这里要注意一点,上面openssl生成私钥的时候格式是这样的:

            -----BEGIN RSA PRIVATE KEY-----
            MIICXgIBAAKBgQDQxvhGw9qrUO5U9FM3J7zgyikG6Fqj48kJf8hWaxUcZaBx9X1g
            6i/JVXshkoXYBfE0EKKpPOOUy0uibAS+88rUGEWLVlozXpqVAVE3fArh/qy/yfva
            RwVlZLD7JpqDdGmpLq2tj8hv7BnOsVKq0Vw2Umn+fmHViC4dHtd/O4FbswIDAQAB
            AoGAOcpp3UTHmdZsMo3zHvhb+ylak/PrayRZeMyrSuiXTmX/NKxMiXApzCRiUhe5
            /uMeMlhMfmZBZOWlSQ93fNgFE5JTCnP45yAtQ5eUd+JkXj3GujSeBFzqbrqJJh9+
            e+aY0jrKGoYa+Z2xq966luyJJFX6Cv2ajZeC+xb8tsa1PFkCQQD4x08z09RaSjxm
            4vZ/3OaWKh8RSXoGEfo8IutXIdWOICGds+zGbHFBDaySUGiSHD9Avyrgg3JkMEjM
            pV8pIqE1AkEA1tZoZyxWVkh5nNfJ3s9FBt86mr+nxc0VCQf6NeKqo3yIGAxDX4PD
            9EE2peG8ew3icz6FGrFlfw9rDGNZpDbORwJBAOYGu+gLBH1byM/FKfD+GsNcPQ+p
            5cb5FmxGSV5ubVyVvx9nPxYVLP7emuNKr/XxYlcGq6meQMX8k0ON4RhS6cUCQQCE
            hjBS7JO5l+2E5cv+KKdw7MTu7qjkqHSAZK5hDRirzsb45p+szNBU3OGEBDLLSa5V
            3swmwiVU8sLbGnISjUhDAkEApiEbjkYMz6X9nvrB7Flk7C0unwcl0DbhNpwiiVdu
            u5PYNflWbOiI5zUBsWyKnUi8Ni52tJXbltZkY+O7UA7PRg==
            -----END RSA PRIVATE KEY-----
            复制

            我们要把最上面的begin和end这行去掉,还有中间的key是换行的,把换行符也要去掉,上面去掉之后最终的格式如下:

              MIICXgIBAAKBgQDQxvhGw9qrUO5U9FM3J7zgyikG6Fqj48kJf8hWaxUcZaBx9X1g6i/JVXshkoXYBfE0EKKpPOOUy0uibAS+88rUGEWLVlozXpqVAVE3fArh/qy/yfvaRwVlZLD7JpqDdGmpLq2tj8hv7BnOsVKq0Vw2Umn+fmHViC4dHtd/O4FbswIDAQABAoGAOcpp3UTHmdZsMo3zHvhb+ylak/PrayRZeMyrSuiXTmX/NKxMiXApzCRiUhe5/uMeMlhMfmZBZOWlSQ93fNgFE5JTCnP45yAtQ5eUd+JkXj3GujSeBFzqbrqJJh9+e+aY0jrKGoYa+Z2xq966luyJJFX6Cv2ajZeC+xb8tsa1PFkCQQD4x08z09RaSjxm4vZ/3OaWKh8RSXoGEfo8IutXIdWOICGds+zGbHFBDaySUGiSHD9Avyrgg3JkMEjMpV8pIqE1AkEA1tZoZyxWVkh5nNfJ3s9FBt86mr+nxc0VCQf6NeKqo3yIGAxDX4PD9EE2peG8ew3icz6FGrFlfw9rDGNZpDbORwJBAOYGu+gLBH1byM/FKfD+GsNcPQ+p5cb5FmxGSV5ubVyVvx9nPxYVLP7emuNKr/XxYlcGq6meQMX8k0ON4RhS6cUCQQCEhjBS7JO5l+2E5cv+KKdw7MTu7qjkqHSAZK5hDRirzsb45p+szNBU3OGEBDLLSa5V3swmwiVU8sLbGnISjUhDAkEApiEbjkYMz6X9nvrB7Flk7C0unwcl0DbhNpwiiVduu5PYNflWbOiI5zUBsWyKnUi8Ni52tJXbltZkY+O7UA7PRg==
              复制


              程序员如何提高解决问题的能力

              Java网络编程之NIO

              MyBatis源码分析四:动态Sql实现

              RabbitMQ Fedration插件


              文章转载自程序员升级之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论