Java之RSAUtil类的使用
我在项目中遇到选择审批人时,传到前端的审批人信息ID需要加密,然后传回后端需要解密的情况。
我们可以采用RSA算法实现公私钥加解密。
RSAUtil类内容如下:
package com.cmit.kapok.system.utils; import com.cmit.kapok.system.api.cdy_encrypt_keys.ICdyEncryptKeysService; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; public class RSAUtil { private static final String RSA = "RSA"; private static final String mode = "RSA/ECB/PKCS1Padding"; private static ICdyEncryptKeysService cdyEncryptKeysService; public static PublicKey getPublicKey(String base64PublicKey) { PublicKey publicKey = null; try { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes())); KeyFactory keyFactory = KeyFactory.getInstance(RSA); publicKey = keyFactory.generatePublic(keySpec); return publicKey; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } return publicKey; } public static String encrypt(String data) throws Exception { if (cdyEncryptKeysService == null) { cdyEncryptKeysService = SpringBeanFactoryUtils.getBean(ICdyEncryptKeysService.class); } String publicKey = cdyEncryptKeysService.getPublicKey(); return Base64.getEncoder().encodeToString(encrypt(data.getBytes(), getPublicKey(publicKey))); } public static byte[] encrypt(byte[] plainBytes, PublicKey publicKey) throws Exception { int keyByteSize = 2048 / 8; int encryptBlockSize = keyByteSize - 11; int nBlock = plainBytes.length / encryptBlockSize; if ((plainBytes.length % encryptBlockSize) != 0) { nBlock += 1; } ByteArrayOutputStream outbuf = null; try { Cipher cipher = Cipher.getInstance(mode); cipher.init(Cipher.ENCRYPT_MODE, publicKey); outbuf = new ByteArrayOutputStream(nBlock * keyByteSize); for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) { int inputLen = plainBytes.length - offset; if (inputLen > encryptBlockSize) { inputLen = encryptBlockSize; } byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen); outbuf.write(encryptedBlock); } outbuf.flush(); return outbuf.toByteArray(); } catch (Exception e) { throw new Exception("ENCRYPT ERROR:", e); } finally { try { if (outbuf != null) { outbuf.close(); } } catch (Exception e) { outbuf = null; throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e); } } } public static PrivateKey getPrivateKey(String base64PrivateKey) { PrivateKey privateKey = null; PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes())); KeyFactory keyFactory = null; try { keyFactory = KeyFactory.getInstance(RSA); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } try { privateKey = keyFactory.generatePrivate(keySpec); } catch (InvalidKeySpecException e) { e.printStackTrace(); } return privateKey; } public static String decrypt(String data, String base64PrivateKey) throws Exception { return new String(decrypt(Base64.getDecoder().decode(data.getBytes()), getPrivateKey(base64PrivateKey))); } public static byte[] decrypt(byte[] encryptedBytes, PrivateKey privateKey) throws Exception { int keyByteSize = 2048 / 8; int decryptBlockSize = keyByteSize - 11; int nBlock = encryptedBytes.length / keyByteSize; ByteArrayOutputStream outbuf = null; try { Cipher cipher = Cipher.getInstance(mode); cipher.init(Cipher.DECRYPT_MODE, privateKey); outbuf = new ByteArrayOutputStream(nBlock * decryptBlockSize); for (int offset = 0; offset < encryptedBytes.length; offset += keyByteSize) { int inputLen = encryptedBytes.length - offset; if (inputLen > keyByteSize) { inputLen = keyByteSize; } byte[] decryptedBlock = cipher.doFinal(encryptedBytes, offset, inputLen); outbuf.write(decryptedBlock); } outbuf.flush(); return outbuf.toByteArray(); } catch (Exception e) { throw new Exception("DEENCRYPT ERROR:", e); } finally { try { if (outbuf != null) { outbuf.close(); } } catch (Exception e) { outbuf = null; throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e); } } } public static void generateKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA); keyPairGen.initialize(2048);//密钥位数 //By default, the private key is generated in PKCS#8 format and the public key is generated in X.509 format. KeyPair keyPair = keyPairGen.generateKeyPair();//密钥对 PublicKey publicKey = keyPair.getPublic(); // 公钥 PrivateKey privateKey = keyPair.getPrivate();// 私钥 System.out.println(Base64.getEncoder().encodeToString(publicKey.getEncoded())); System.out.println(Base64.getEncoder().encodeToString(privateKey.getEncoded())); } public static void main(String[] args) throws NoSuchAlgorithmException { generateKeyPair(); } }
1.使用generateKeyPair可以生成一对base64编码的公私钥,可手动存储在数据库表里。
2.调用encrypt(str),函数内部会调用getPublicKey从数据库获取公钥,然后调用encrpt(byte[],publicKey),然后再构造成字符串。
3.调用decrypt(str,base64PrivateKey),函数内部会调用getPrivateKey获取私钥,然后调用decrypt(byte[],privateKey),然后再构造成字符串。