RSA非对称加密

java RSA 分段分组加密


 

文中公钥和私钥都从resource下去加载的,你可以直接使用字符串也是可以的

一般情况使用公钥加密,私钥解密

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.core.io.ClassPathResource;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author Mr.Fang
 * @version 1.0
 * @description: RAS 非对称加密解密 2048
 * @date 2022/5/12 11:06
 */
public class RSAUtil {

    /**
     * 1024 加密最大块 117
     * 最大文件加密块 2048 不能超过 245
     */
    private static final int MAX_ENCRYPT_BLOCK = 245;

    /**
     * 1024 解密最大块 128
     * 最大文件解密块 2048 不能超过 256
     */
    private static final int MAX_DECRYPT_BLOCK = 256;

    /**
     * 字符集
     */
    private static final String CHAR_SET_NAME = "UTF-8";

    /**
     * 加密类型
     */
    private static final String ENCRYPT_TYPE = "RSA";


    /**
     * description:  创建秘钥对 公钥和私钥
     * create by: Mr.Fang
     *
     * @param keySize: 秘钥字节数
     * @date: 2022/5/17 10:33
     */
    public RSAUtil.RSAKey createKey(int keySize) {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ENCRYPT_TYPE);
            keyPairGenerator.initialize(keySize);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
            PrivateKey privateKey = keyPair.getPrivate();
            String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
            return new RSAUtil.RSAKey(privateKeyStr, publicKeyStr);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class RSAKey {
        private String privateKey;
        private String publicKey;
    }

    /**
     * description:  从 resource 加载公钥
     * create by: Mr.Fang
     *
     * @return: java.security.interfaces.RSAPublicKey
     * @date: 2022/5/17 9:27
     */
    private static RSAPublicKey getPublicKey() {
        try {
            ClassPathResource resource = new ClassPathResource("publicKey");
            InputStream inputStream = null;
            try {
                inputStream = resource.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            //将流转为字符串
            String string = readToString(inputStream);
            KeyFactory keyFactory = KeyFactory.getInstance(ENCRYPT_TYPE);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getMimeDecoder().decode(string));
            RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(x509EncodedKeySpec);
            return publicKey;
        } catch (NoSuchAlgorithmException var4) {
            var4.printStackTrace();
        } catch (InvalidKeySpecException var5) {
            var5.printStackTrace();
        }
        return null;
    }


    /**
     * description: 从 resource 加载私钥
     * create by: Mr.Fang
     *
     * @return: java.security.interfaces.RSAPrivateKey
     * @date: 2022/5/17 9:12
     */
    private static RSAPrivateKey getPrivateKey() {
        ClassPathResource resource = new ClassPathResource("privateKey");
        try (InputStream inputStream = resource.getInputStream()) {
            String privateKeyStr = readToString(inputStream);
            KeyFactory keyFactory = KeyFactory.getInstance(ENCRYPT_TYPE);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(privateKeyStr));
            RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            return privateKey;
        } catch (NoSuchAlgorithmException var4) {
            var4.printStackTrace();
        } catch (InvalidKeySpecException var5) {
            var5.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * description: 输入流转字符串
     * create by: Mr.Fang
     *
     * @param inputStream: 输入流
     * @return: java.lang.String
     * @date: 2022/5/18 8:53
     */
    public static String readToString(InputStream inputStream) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, CHAR_SET_NAME));
            StringBuffer sb = new StringBuffer();
            for (String s = reader.readLine(); s != null; s = reader.readLine()) {
                sb.append(s);
            }
            String toString = sb.toString();
            return toString;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * description:   分段公钥加密
     * create by: Mr.Fang
     *
     * @param inputStr: 待加密数据
     * @return: java.lang.String
     * @date: 2022/5/17 9:26
     */
    public static String publicEncrypt(String inputStr) {
        try {
            // 获取 cipher 加密对象
            Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE);
            // 获取公钥
            RSAPublicKey rsaPublicKey = getPublicKey();
            // 初始化加密对象 第一个参数加密模式,第二个参数公钥
            cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
            // 加密字符串转字节数组
            byte[] bytes = inputStr.getBytes(CHAR_SET_NAME);
            // 字节长度
            int length = bytes.length;
            // 偏移
            int offset = 0;
            // 当前下标
            int i = 0;
            // 创建字节输出流
            ByteArrayOutputStream byOutput = new ByteArrayOutputStream();
            while (length - offset > 0) {
                // 存放每次加密后的字节
                byte[] cache; //
                if (length - offset > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(bytes, offset, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(bytes, offset, length - offset);
                }
                // 写入字节流
                byOutput.write(cache);
                i++; // 自增
                offset = MAX_ENCRYPT_BLOCK * i; // 偏移
            }
            byOutput.flush(); // 刷新
            byOutput.close(); // 关闭字节流
            // 转字节数组
            byte[] byteArray = byOutput.toByteArray();
            // base64 编码
            return Base64.getEncoder().encodeToString(byteArray);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * description: 分段私钥解密
     * create by: Mr.Fang
     *
     * @param inputStr: 密文
     * @return: java.lang.String
     * @date: 2022/5/17 9:20
     */
    public static String privateDecrypt(String inputStr) throws Exception {
        // 获取 cipher 加密对象
        Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE);
        //获取私钥
        PrivateKey privateKey = getPrivateKey();
        // 初始化 cipher 对象,第一个参数解密模式,第二个参数解密秘钥
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        // base64 解码
        byte[] bytes = Base64.getDecoder().decode(inputStr);
        // 字节长度
        int length = bytes.length;
        // 偏移
        int offset = 0;
        // 当前下标
        int i = 0;
        // 创建字节输出流
        ByteArrayOutputStream byOutput = new ByteArrayOutputStream();
        while (length - offset > 0) {
            // 存放每次机密后的字节
            byte[] cache; //
            if (length - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(bytes, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(bytes, offset, length - offset);
            }
            // 写入字节流
            byOutput.write(cache);
            i++; // 自增
            offset = MAX_DECRYPT_BLOCK * i; // 偏移
        }
        byOutput.flush(); // 刷新
        byOutput.close(); // 关闭字节流
        // 转字节数组
        byte[] byteArray = byOutput.toByteArray();
        return new String(byteArray, CHAR_SET_NAME);
    }
}

 测试结果

 

 

 

posted @ 2022-05-18 09:11  天葬  阅读(9)  评论(0编辑  收藏  举报