我们在项目开发中,难免会遇到敏感数据的传输,此时就会考虑大数据传输的加密,这里分享了一个加密解密的小demo,可供讨论学习研究。
这里介绍的是:rsa-encrypt-body-spring-boot的加解密方式
Spring Boot接口加密,可以对返回值、参数值通过注解的方式自动加解密
1. pom文件引入包
<!--参数和返回值的加解密-->
<dependency>
<groupId>cn.shuibo</groupId>
<artifactId>rsa-encrypt-body-spring-boot</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<!--参数和返回值的加解密-->
2. 在application.yml配置加解密的公钥私钥
或在application.properties文件中配置也可以,这里我使用的yml方式配置
######RSA的公钥及私钥
rsa:
encrypt:
open: true # 是否开启加密 true or false
showLog: true # 是否打印加解密log true or false
debug: false # true表示开启调试,不加密。(方便开发时测试)
publicKey: MIGfMA0GCSq(公钥)
privateKey: MIICdQIBADANBgkqh(私钥)
(对应私钥公钥对的生成,可在网上自行生成)
3. Application启动类添加注解
需在SpringBoot项目的Application启动类添加注解 @EnableSecurity
@SpringBootApplication
@EnableSecurity
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
4. 接口对返回值进行加密
在接口返回数据的时,数据加密使用注解:@Encrypt
@Encrypt
@ResponseBody
@RequestMapping(value = "/get-demo",method=RequestMethod.POST)
public Map<String, Object> getMapDemo(@RequestBody DemoBean param){
Map<String, Object> map=new HashMap<>();
map.put("data","自己的数据信息");
return map;
}
5. 接口接受加密参数
在接口处接收加密的数据,使用注解:@Decrypt
@Decrypt
@ResponseBody
@RequestMapping(value = "/add-golddetails", method = RequestMethod.POST)
public Object addDemoBean(@RequestBody DemoBean param){
Map<String, Object> map=new HashMap<>();
map.put("data","自己的数据信息");
return map;
}
PostMan测试返回的加密数据
6. 分享加解密的工具类
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.util.Base64Utils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import java.io.IOException;
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;
/***
* RSA加解密工具类
*/
public class RSAUtilTools {
public static final String PUBLIC_KEY_VALUES ="MIGfMA0GCSqGS(公钥)";
public static final String PRIVATE_KEY_VALUES ="MIICdQIBADANBgkqhkiG9w0BAQEF(私钥)";
/**
* RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024
*/
public static final int KEY_SIZE = 128;
/**
* 生成公钥、私钥对(keysize=1024)
*/
public static RSAUtilTools.KeyPairInfo getKeyPair() {
return getKeyPair(KEY_SIZE);
}
/**
* 生成公钥、私钥对
*
* @param keySize
* @return
*/
public static RSAUtilTools.KeyPairInfo getKeyPair(int keySize) {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(keySize);
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私钥
RSAPrivateKey oraprivateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公钥
RSAPublicKey orapublicKey = (RSAPublicKey) keyPair.getPublic();
RSAUtilTools.KeyPairInfo pairInfo = new RSAUtilTools.KeyPairInfo(keySize);
//公钥
byte[] publicKeybyte = orapublicKey.getEncoded();
String publicKeyString = Base64.encodeBase64String(publicKeybyte);
pairInfo.setPublicKey(publicKeyString);
//私钥
byte[] privateKeybyte = oraprivateKey.getEncoded();
String privateKeyString = Base64.encodeBase64String(privateKeybyte);
pairInfo.setPrivateKey(privateKeyString);
return pairInfo;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取公钥对象
*
* @param publicKeyBase64
* @return
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
*/
public static PublicKey getPublicKey(String publicKeyBase64)
throws InvalidKeySpecException, NoSuchAlgorithmException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicpkcs8KeySpec =
new X509EncodedKeySpec(Base64.decodeBase64(publicKeyBase64));
PublicKey publicKey = keyFactory.generatePublic(publicpkcs8KeySpec);
return publicKey;
}
/**
* 获取私钥对象
*
* @param privateKeyBase64
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public static PrivateKey getPrivateKey(String privateKeyBase64)
throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privatekcs8KeySpec =
new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyBase64));
PrivateKey privateKey = keyFactory.generatePrivate(privatekcs8KeySpec);
return privateKey;
}
/**
* 使用工钥加密
*
* @param content 待加密内容
* @param publicKeyBase64 公钥 base64 编码
* @return 经过 base64 编码后的字符串
*/
public static String encipher(String content, String publicKeyBase64) {
return encipher(content, publicKeyBase64, KEY_SIZE / 8 - 11);
}
/**
* 使用公司钥加密(分段加密)
*
* @param content 待加密内容
* @param publicKeyBase64 公钥 base64 编码
* @param segmentSize 分段大小,一般小于 keySize/8(段小于等于0时,将不使用分段加密)
* @return 经过 base64 编码后的字符串
*/
public static String encipher(String content, String publicKeyBase64, int segmentSize) {
try {
PublicKey publicKey = getPublicKey(publicKeyBase64);
return encipher(content, publicKey, segmentSize);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 分段加密
*
* @param ciphertext 密文
* @param key 加密秘钥
* @param segmentSize 分段大小,<=0 不分段
* @return
*/
public static String encipher(String ciphertext, java.security.Key key, int segmentSize) {
try {
// 用公钥加密
byte[] srcBytes = ciphertext.getBytes();
// Cipher负责完成加密或解密工作,基于RSA
Cipher cipher = Cipher.getInstance("RSA");
// 根据公钥,对Cipher对象进行初始化
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] resultBytes = null;
if (segmentSize > 0)
resultBytes = cipherDoFinal(cipher, srcBytes, segmentSize); //分段加密
else
resultBytes = cipher.doFinal(srcBytes);
String base64Str = Base64Utils.encodeToString(resultBytes);
return base64Str;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 分段大小
*
* @param cipher
* @param srcBytes
* @param segmentSize
* @return
* @throws IllegalBlockSizeException
* @throws BadPaddingException
* @throws IOException
*/
public static byte[] cipherDoFinal(Cipher cipher, byte[] srcBytes, int segmentSize)
throws IllegalBlockSizeException, BadPaddingException, IOException {
if (segmentSize <= 0)
throw new RuntimeException("分段大小必须大于0");
ByteArrayOutputStream out = new ByteArrayOutputStream();
int inputLen = srcBytes.length;
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > segmentSize) {
cache = cipher.doFinal(srcBytes, offSet, segmentSize);
} else {
cache = cipher.doFinal(srcBytes, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * segmentSize;
}
byte[] data = out.toByteArray();
out.close();
return data;
}
/**
* 使用私钥解密
*
* @param contentBase64 待加密内容,base64 编码
* @param privateKeyBase64 私钥 base64 编码
* @return
* @segmentSize 分段大小
*/
public static String decipher(String contentBase64, String privateKeyBase64) {
return decipher(contentBase64, privateKeyBase64, KEY_SIZE / 8);
}
/**
* 使用私钥解密(分段解密)
*
* @param contentBase64 待加密内容,base64 编码
* @param privateKeyBase64 私钥 base64 编码
* @return
* @segmentSize 分段大小
*/
public static String decipher(String contentBase64, String privateKeyBase64, int segmentSize) {
try {
PrivateKey privateKey = getPrivateKey(privateKeyBase64);
return decipher(contentBase64, privateKey, segmentSize);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 分段解密
*
* @param contentBase64 密文
* @param key 解密秘钥
* @param segmentSize 分段大小(小于等于0不分段)
* @return
*/
public static String decipher(String contentBase64, java.security.Key key, int segmentSize) {
try {
// 用私钥解密
byte[] srcBytes = Base64Utils.decodeFromString(contentBase64);
// Cipher负责完成加密或解密工作,基于RSA
Cipher deCipher = Cipher.getInstance("RSA");
// 根据公钥,对Cipher对象进行初始化
deCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decBytes = null;//deCipher.doFinal(srcBytes);
if (segmentSize > 0)
decBytes = cipherDoFinal(deCipher, srcBytes, segmentSize); //分段加密
else
decBytes = deCipher.doFinal(srcBytes);
String decrytStr = new String(decBytes);
return decrytStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 秘钥对
*/
public static class KeyPairInfo {
String privateKey;
String publicKey;
int keySize = 0;
public KeyPairInfo(int keySize) {
setKeySize(keySize);
}
public KeyPairInfo(String publicKey, String privateKey) {
setPrivateKey(privateKey);
setPublicKey(publicKey);
}
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getPublicKey() {
return publicKey;
}
public void setPublicKey(String publicKey) {
this.publicKey = publicKey;
}
public int getKeySize() {
return keySize;
}
public void setKeySize(int keySize) {
this.keySize = keySize;
}
}
/***测试***/
public static void main(String[] args) {
//String encryptedString="ZKUIG9/";
//System.out.println(RSAUtilTools.decipher(encryptedString, PRIVATE_KEY_VALUES, 128));
String miwen="cGAMp9gaq7IoTouYJs=";
try {
System.out.println(RSAUtilTools.decipher(miwen, PRIVATE_KEY_VALUES, 128));
}catch (Exception e){
System.out.println("错误:"+e);
}
}
}