我在项目中遇到选择审批人时,传到前端的审批人信息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),然后再构造成字符串。