Java使用RSA加解密进行第三方接口测试

RSA工具类,这个就是网上大多数通用的代码了,无非就是生成密钥,获取公,私钥,分段加解密这些了。
注意:1、RSA默认支持最大加密的为117位,解密的为128,如果你的内容超出了就必须要进行分段加解密。刚一开始楼主报的错误就是因为这一个。
2、还有一个要提一下的,毕竟曾经掉进过坑里。1024位的密钥和2048位的密钥解密最大分别对应128和256,我下面打了注释的,多留意一下。

package com.qyq.springbootapi.util;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class RsaUtil {

    /**
     * 指定加密算法
     */
    private static final String KEY_ALGORITHM = "RSA";

    /**
     * 指定生成多少位的密钥
     */
    private static final int KEY_BIT = 1024;

    /** *//**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /** *//**
     * RSA最大解密密文大小
     * 1024位密钥的要设置为128,
     * 248位密钥的要改成256,不然会报错
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * 生成密钥对
     * @return
     * @throws Exception
     */
    public static Map genKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGenerator.initialize(KEY_BIT);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();//生成公钥
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();//生成密钥
        Map map = new HashMap<>(2);
        map.put("publicKey",rsaPublicKey);
        map.put("privateKey",rsaPrivateKey);
        return map;
    }

    /**
     * 获取公钥
     * @param map
     * @return
     */
    public static String getPublicKey(Map map){
        Key key = (Key) map.get("publicKey");
        String publicKey = Base64.getEncoder().encodeToString(key.getEncoded());
        return publicKey;
    }

    /**
     * 获取私钥
     * @param map
     * @return
     */
    public static String getPrivate(Map map){
        Key key = (Key) map.get("privateKey");
        String privateKey = Base64.getEncoder().encodeToString(key.getEncoded());
        return privateKey;
    }

    /**
     * 公钥分段加密 --》公钥加密
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String encrypt(String data, String publicKey) throws Exception {
        byte[] bytes = Base64.getDecoder().decode(publicKey);//先把公钥进行解码
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(bytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(x509EncodedKeySpec);

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.getBytes("UTF-8").length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data.getBytes("UTF-8"), offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data.getBytes("UTF-8"), offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
        // 加密后的字符串
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 私钥分段解密 --》私钥解密
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static String decrypt(String data, String privateKey) throws Exception {
        byte[] bytes = Base64.getDecoder().decode(privateKey);//先对私钥进行解码
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        byte[] dataBytes = Base64.getDecoder().decode(data);//对要解密的数据进行解码
        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        // 解密后的内容
        return new String(decryptedData, "UTF-8");
    }




}

@GetMapping("/test")
    public ResponseResult TestApiController(){
        String object = restTemplate.getForObject("http://localhost:8080/get", String.class);
        String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMcJilCfGtsoXe/ioAqT2sh36bz2j+KmUUcaKaF+dQNQ/LKTZNyftazl44Oyl6gEGfSYkFgGiCMutv6EMHlPRV6AYL8VNo8BmcDGDfWWyL3fDIpxtD99IXLV7k0f7Hm4doEuaEEb9pY3+wpAYe2Fr41MLRv4kI9nG7/OH24/cTHdAgMBAAECgYATKFPr1qSbG5OPF10YJ4sTaJdS3NiUlDWWhmojZSyWGSF5fr5ijezKq4Xuky4NufdVl6mtD1PjLwfmD4sq4fpnJqfAuUMUGe3NC9Y6hm3VqWdXqY9UrRaQQUUsPlQlxaMYCOwjPdgvk3BRkIet1vY/63EWjrFfXXqhb+GpgKz68QJBAO4/FZI7E9lK8BMRodrT44rB1W0hV/nan0Lel2ZSoZf0QhChCtQLP6WJ3rfC1IQHmL9ZWVqD1fzndXEHyAJcUmcCQQDV3ns0lVFll76dGZ0VEB8G+vVD7L8TIpJSuCaRKf4KZXIWoOUIoefgNEEW8AGF9EwkPlUNFrSXahEeyvjFgNcbAkAvqKLyC6tezmTUC7TrB3P/L+M333Gv45H0WH7E00bMFOqaVPzLiiyDOt84t1q3xqVBsefz+Wd3Hf4aTEowXrOFAkBrPi/r00BIwEnd/z0MldPpLSiV0f6SetCC2ELGohb4YZxPCokuxfk/LRTCisFIyZLwzazabltKXe6N0VvjtdKnAkEAxxToDiKLandMMcAZjpeQS57ENSq17DVA7v3ZCl5W9wIIi7zGwcfUFZ/Uwwk55+Hrx/DmBqxQjhGanPzp9XWMVw==";

        try {
            String decrypt = RsaUtil.decrypt(object, privateKey);
            return new ResponseResult(0,"成功",decrypt);

        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult(0,"失败",404);
        }


    }
@GetMapping("/get")
    public String TestApiController1(){
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHCYpQnxrbKF3v4qAKk9rId+m89o/iplFHGimhfnUDUPyyk2Tcn7Ws5eODspeoBBn0mJBYBogjLrb+hDB5T0VegGC/FTaPAZnAxg31lsi93wyKcbQ/fSFy1e5NH+x5uHaBLmhBG/aWN/sKQGHtha+NTC0b+JCPZxu/zh9uP3Ex3QIDAQAB";
        String data = "这是一个测试接口";

        try {
            String encrypt = RsaUtil.encrypt(data, publicKey);
            return encrypt;

        } catch (Exception e) {
            e.printStackTrace();
            return "null";
        }

    }


万事俱备只欠东风了,结果运行时他又给我抛出了一个错,后面还是靠度娘解决了,现在贴一下,就是下面这个错
Java使用RSA加解密进行第三方接口测试_第1张图片
java.lang.IllegalArgumentException: Illegal base64 character 22
狗日的,原来是因为导的包造成的。
Base64这个东西因为我导的是java.util.Base64这个包下的,jdk1.8后用的编码表不一样,不包括换行符。后面还是改成使用apache common包中的org.apache.commons.codec.binary.Base64类进行编码和解码才解决。

由于jdk1.7和jdk1.8内置的Base64遵守的RFC协议不一致,jdk1.7按照照RFC1521实现的,jdk1.8是按照rfc4648和rfc2045两个协议来实现的。具体可以从类注释中查询到。由于协议的不同可能导致jdk1.8的解码jdk1.7编码的数据时抛出java.lang.IllegalArgumentException: Illegal base64 character a异常.因此需要特别注意保持解码编码的一致性。
jdk7的编码结果包含换行;
jdk8的编码结果不包含换行;
jdk8无法解码包含换行的编码结果;

你可能感兴趣的:(RSA加解密,RSA,非对称加解密算法)