1. 程式人生 > 其它 >RSA非對稱加密

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); } }

 測試結果