> 文档中心 > Java加密算法—非对称加密

Java加密算法—非对称加密

目录

  • 1、概述
  • 2、对称加密、解密实现

1、概述

与对称加密算法不同,非对称加密算法需要两个密钥公开密钥(publickey)私有密钥(privatekey),公开密钥和私有密钥是一对,如果用公开密钥加密需要私有密钥解密,反之用私有密钥加密需要公开密钥解密,因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

特点:

  • 加密和解密使用不同的密钥。
  • 如果使用私钥加密, 只能使用公钥解密。
  • 如果使用公钥加密, 只能使用私钥解密。
  • 安全级别高,处理数据的速度较慢。

注意:
理论上私钥是可以推导出公钥的,公钥无法推导出私钥。

私钥中获取公钥测试地址:http://tool.chacuo.net/cryptgetpubkey

2、对称加密、解密实现

将非对称加密的两种方式进行封装处理,达到一套代码实现两种加密方式,代码可以直进行使用。

public class AsymmetricTest {    private final static String RSA = "RSA";    public static void main(String[] args) { // 加密密文 String input = "key=85CD019515D14B91AD942787532314FF&startTime=1629431243245&endTime=1660967243244"; // 生成密钥对文件,在实际开发中,根据实际需求生成文件位置 String pubPath = "C:\\Users\\Desktop\\publicKey.pub"; String priPath = "C:\\Users\\Desktop\\privateKey.pri"; // 生成公钥和私钥文件,并且打印公钥的字符串和私钥字符串 generateKeyPair(pubPath, priPath); System.out.println("\n==============================================\n"); // 从文件中加载密钥 PublicKey publicKey = loadPublicKeyFromFile(pubPath); PrivateKey privateKey = loadPrivateKeyFromFile(priPath); // 公钥加密,私钥解密 String encrypted = encryptByAsymmetric(input, publicKey); System.out.println("非对称RSA-公钥加密:" + encrypted); System.out.println("非对称RSA-私钥解密:" + decryptByAsymmetric(encrypted, privateKey)); System.out.println("\n==============================================\n"); // 私钥加密,公钥解密 String encrypted2 = encryptByAsymmetric(input, privateKey); System.out.println("非对称RSA-私钥加密:" + encrypted2); System.out.println("非对称RSA-公钥解密:" + decryptByAsymmetric(encrypted2, publicKey));    }    /**     * 从文件中加载公钥     *     * @param filePath : 文件路径     * @return : 公钥     * @throws Exception     */    public static PublicKey loadPublicKeyFromFile(String filePath) { try {     // 将文件内容转为字符串     String keyString = FileUtils.readFileToString(new File(filePath), String.valueOf(StandardCharsets.UTF_8));     return loadPublicKeyFromString(keyString); } catch (Exception e) {     e.printStackTrace();     throw new RuntimeException("获取公钥文件字符串失败!"); }    }    /**     * 从文件中加载私钥     *     * @param filePath : 文件路径     * @return : 私钥     * @throws Exception     */    public static PrivateKey loadPrivateKeyFromFile(String filePath) { try {     // 将文件内容转为字符串     String keyString = FileUtils.readFileToString(new File(filePath), String.valueOf(StandardCharsets.UTF_8));     return loadPrivateKeyFromString(keyString); } catch (Exception e) {     e.printStackTrace();     throw new RuntimeException("获取私钥文件字符串失败!"); }    }    /**     * 从字符串中加载公钥     *     * @param keyString : 公钥     * @return : 公钥     * @throws Exception     */    public static PublicKey loadPublicKeyFromString(String keyString) { try {     // 进行Base64解码     byte[] decode = Base64.decode(keyString);     // 获取密钥工厂     KeyFactory keyFactory = KeyFactory.getInstance(RSA);     // 构建密钥规范     X509EncodedKeySpec key = new X509EncodedKeySpec(decode);     // 获取公钥     return keyFactory.generatePublic(key); } catch (Exception e) {     e.printStackTrace();     throw new RuntimeException("获取公钥失败!"); }    }    /**     * 从字符串中加载私钥     *     * @param keyString : 私钥     * @return : 私钥     * @throws Exception     */    public static PrivateKey loadPrivateKeyFromString(String keyString) { try {     // 进行Base64解码     byte[] decode = Base64.decode(keyString);     // 获取密钥工厂     KeyFactory keyFactory = KeyFactory.getInstance(RSA);     // 构建密钥规范     PKCS8EncodedKeySpec key = new PKCS8EncodedKeySpec(decode);     // 生成私钥     return keyFactory.generatePrivate(key); } catch (Exception e) {     e.printStackTrace();     throw new RuntimeException("获取私钥失败!"); }    }    /**     * 打印密钥对并且保存到文件     *     * @return     */    public static void generateKeyPair(String pubPath, String priPath) { try {     //  创建密钥对生成器对象     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);     // 生成密钥对     KeyPair keyPair = keyPairGenerator.generateKeyPair();     PrivateKey privateKey = keyPair.getPrivate();     PublicKey publicKey = keyPair.getPublic();     String privateKeyString = Base64.encode(privateKey.getEncoded());     String publicKeyString = Base64.encode(publicKey.getEncoded());     System.out.println("私钥:" + privateKeyString);     System.out.println("公钥:" + publicKeyString);     // 保存文件     if (pubPath != null) {  FileUtils.writeStringToFile(new File(pubPath), publicKeyString, String.valueOf(StandardCharsets.UTF_8));     }     if (priPath != null) {  FileUtils.writeStringToFile(new File(priPath), privateKeyString, String.valueOf(StandardCharsets.UTF_8));     } } catch (Exception e) {     e.printStackTrace();     throw new RuntimeException("生成密钥对失败!"); }    }    /**     * 非对称加密数据     *     * @param input : 原文     * @param key   : 密钥     * @return : 密文     * @throws Exception     */    public static String encryptByAsymmetric(String input, Key key) { try {     // 获取Cipher对象     Cipher cipher = Cipher.getInstance(RSA);     // 初始化模式(加密)和密钥     cipher.init(Cipher.ENCRYPT_MODE, key);     byte[] resultBytes = getMaxResultEncrypt(input, cipher);     return Base64.encode(resultBytes); } catch (Exception e) {     e.printStackTrace();     throw new RuntimeException("加密失败!"); }    }    /**     * 非对称解密数据     *     * @param encrypted : 密文     * @param key: 密钥     * @return : 原文     * @throws Exception     */    public static String decryptByAsymmetric(String encrypted, Key key) { try {     // 获取Cipher对象     Cipher cipher = Cipher.getInstance(RSA);     // 初始化模式(解密)和密钥     cipher.init(Cipher.DECRYPT_MODE, key);     return new String(getMaxResultDecrypt(encrypted, cipher)); } catch (  Exception e) {     e.printStackTrace();     throw new RuntimeException("解密失败!"); }    }    /**     * 分段处理加密数据     *     * @param input  : 加密文本     * @param cipher : Cipher对象     * @return     */    private static byte[] getMaxResultEncrypt(String input, Cipher cipher) throws Exception { byte[] inputArray = input.getBytes(); int inputLength = inputArray.length; // 最大加密字节数,超出最大字节数需要分组加密 int MAX_ENCRYPT_BLOCK = 117; // 标识 int offSet = 0; byte[] resultBytes = {}; byte[] cache = {}; while (inputLength - offSet > 0) {     if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {  cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK);  offSet += MAX_ENCRYPT_BLOCK;     } else {  cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);  offSet = inputLength;     }     resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);     System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length); } return resultBytes;    }    /**     * 分段处理解密数据     *     * @param decryptText : 加密文本     * @param cipher      : Cipher对象     * @throws Exception     */    private static byte[] getMaxResultDecrypt(String decryptText, Cipher cipher) throws Exception { byte[] inputArray = Base64.decode(decryptText.getBytes(StandardCharsets.UTF_8)); int inputLength = inputArray.length; // 最大解密字节数,超出最大字节数需要分组加密 int MAX_ENCRYPT_BLOCK = 128; // 标识 int offSet = 0; byte[] resultBytes = {}; byte[] cache = {}; while (inputLength - offSet > 0) {     if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {  cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK);  offSet += MAX_ENCRYPT_BLOCK;     } else {  cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);  offSet = inputLength;     }     resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);     System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length); } return resultBytes;    }}

效果:
Java加密算法—非对称加密