一. 背景
- 由于最近项目对接的双方需要加密传输数据,还想做的轻量级一些,因此在网上找了一些成熟安全的加密算法,最后选定非对称加密算法
RSA
。 - 双方加解密的方案
- 每个公私钥对只使用一次,用于实时加解密
- 每个公私钥对永久存在,用于加解密不同步、以及多次加解密使用相同公私钥对的场景。
二. 实践
- 由于项目需要使用第二种方案,公私钥对需要在项目中永久存储,因此提前生成公私钥对,存储在文件中。每次加解密都取出来使用。
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.crypto.Cipher;
import java.io.InputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;
import java.util.Properties;
@Component
public class RSAEncryptManager {
private static final String PUBLIC_KEY = "publicKey";
private static final String PRIVATE_KEY = "privateKey";
private static final String RSA = "RSA";
private static final String UTF_8 = "UTF-8";
private static final String BLIND_RSA_KEY_FILE = "blind_rsa_key.properties";
private RSAPublicKey pubKey;
private RSAPrivateKey priKey;
@PostConstruct
private void loadRSAEncryptKey(){
try {
Properties properties = new Properties();
InputStream in = getClass().getClassLoader().getResourceAsStream(BLIND_RSA_KEY_FILE);
properties.load(in);
byte[] decodedPub = Base64.decodeBase64(properties.getProperty(PUBLIC_KEY));
pubKey = (RSAPublicKey) KeyFactory.getInstance(RSA).generatePublic(new X509EncodedKeySpec(decodedPub));
byte[] decodedPri = Base64.decodeBase64(properties.getProperty(PRIVATE_KEY));
priKey = (RSAPrivateKey) KeyFactory.getInstance(RSA).generatePrivate(new PKCS8EncodedKeySpec(decodedPri));
}catch (Exception e){
LogBusUtil.error(LogDesConstant.CLINICAL_DRUG, "RSA对称加密公私钥初始化异常", e, "time={}", System.currentTimeMillis());
}
}
public String encrypt(String originData){
try {
Cipher cipher = Cipher.getInstance(RSA);
if(pubKey==null){
throw new BizException("RSA公钥为空","RSA公钥为空");
}
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return Base64.encodeBase64String(cipher.doFinal(originData.getBytes(UTF_8)));
}catch (Exception e){
LogBusUtil.error(LogDesConstant.CLINICAL_DRUG, "RSA公钥加密异常", e, "originData={}", originData);
return null;
}
}
public String decrypt(String encData){
try {
byte[] inputByte = Base64.decodeBase64(encData.getBytes(UTF_8));
Cipher cipher = Cipher.getInstance(RSA);
if(priKey==null){
throw new BizException("RSA私钥为空","RSA私钥为空");
}
cipher.init(Cipher.DECRYPT_MODE, priKey);
return new String(cipher.doFinal(inputByte));
}catch (Exception e){
LogBusUtil.error(LogDesConstant.CLINICAL_DRUG, "RSA私钥解密异常", e, "encData={}", encData);
return null;
}
}
public Pair<String, String> randomGenKeyPair(){
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
System.out.println("privateKey:" + privateKeyString);
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
System.out.println("publicKey:" + publicKeyString);
return new ImmutablePair<String, String>(publicKeyString, privateKeyString);
}catch (Exception e){
LogBusUtil.error(LogDesConstant.CLINICAL_DRUG, "RSA随机生成密钥对异常", e, "time={}", System.currentTimeMillis());
return new ImmutablePair<>(null, null);
}
}
}
blind_rsa_key.properties
文件
publicKey=XXXXX
privateKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX