今天公司需求和别的公司要进行第三方接口对接,自己先写的一个小demo拿来跑跑
其中涉及到RSA非对称的加解密算法和AES的对称加解密算法,下面是楼主参考别人然后自己改了一下的工具类。
AES生成密钥,加解密工具类AESutil
package com.qyq.springbootapi.util;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* AES生成密钥,加解密工具类
*/
public class AesUtil {
/**
* 指定加密算法
*/
private static final String KEY_ALGORITHM = "AES";
/**
* 指定生成多少位的密钥
*/
private static final int KEY_BIT = 128;
/**
* 随机生成AES密钥
* @return
* @throws Exception
*/
public static String getGenerateKey()throws Exception{
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
keyGenerator.init(KEY_BIT);
SecretKey secretKey = keyGenerator.generateKey();
byte[] encoded = secretKey.getEncoded();
return Base64.encodeBase64String(encoded);
}
/**
* 将String类型的密钥转化为SecretKey类型
* @param generateKey
* @return
*/
private static SecretKey StringToSecretKey(String generateKey){
byte[] bytes = Base64.decodeBase64(generateKey);
SecretKeySpec spec = new SecretKeySpec(bytes,KEY_ALGORITHM);
return spec;
}
/**
* 加密
* @param data
* @param generateKey
* @return
* @throws Exception
*/
public static String encrypt(String data, String generateKey)throws Exception{
SecretKey secretKey = StringToSecretKey(generateKey);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,secretKey);
byte[] aFinal = cipher.doFinal(data.getBytes("UTF-8"));
return Base64.encodeBase64String(aFinal);
}
/**
* 解密
* @param data
* @param generateKey
* @return
* @throws Exception
*/
public static String decrypt(String data, String generateKey)throws Exception{
SecretKey secretKey = StringToSecretKey(generateKey);
byte[] bytes = Base64.decodeBase64(data);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,secretKey);
byte[] aFinal = cipher.doFinal(bytes);
return new String(aFinal,"UTF-8");
}
}
RSA加解密工具类:
package com.qyq.springbootapi.util;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
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.Base64;
import java.util.HashMap;
import java.util.Map;
public class RsaUtil {
/**
* 指定加密算法
*/
private static final String KEY_ALGORITHM = "RSA";
/**
* 指定生成多少位的密钥
*/
private static final int KEY_BIT = 1024;
/** *//**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/** *//**
* RSA最大解密密文大小
* 1024位密钥的要设置为128,
* 248位密钥的要改成256,不然会报错
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 生成密钥对
* @return
* @throws Exception
*/
public static Map genKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGenerator.initialize(KEY_BIT);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();//生成公钥
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();//生成密钥
Map map = new HashMap<>(2);
map.put("publicKey",rsaPublicKey);
map.put("privateKey",rsaPrivateKey);
return map;
}
/**
* 获取公钥
* @param map
* @return
*/
public static String getPublicKey(Map map){
Key key = (Key) map.get("publicKey");
String publicKey = Base64.getEncoder().encodeToString(key.getEncoded());
return publicKey;
}
/**
* 获取私钥
* @param map
* @return
*/
public static String getPrivate(Map map){
Key key = (Key) map.get("privateKey");
String privateKey = Base64.getEncoder().encodeToString(key.getEncoded());
return privateKey;
}
/**
* 公钥分段加密 --》公钥加密
* @param data
* @param publicKey
* @return
* @throws Exception
*/
public static String encrypt(String data, String publicKey) throws Exception {
byte[] bytes = Base64.getDecoder().decode(publicKey);//先把公钥进行解码
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(bytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicK = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.getBytes("UTF-8").length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data.getBytes("UTF-8"), offset, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes("UTF-8"), offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
// 加密后的字符串
return Base64.getEncoder().encodeToString(encryptedData);
}
/**
* 私钥分段解密 --》私钥解密
* @param data
* @param privateKey
* @return
* @throws Exception
*/
public static String decrypt(String data, String privateKey) throws Exception {
byte[] bytes = Base64.getDecoder().decode(privateKey);//先对私钥进行解码
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateK = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
byte[] dataBytes = Base64.getDecoder().decode(data);//对要解密的数据进行解码
int inputLen = dataBytes.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的内容
return new String(decryptedData, "UTF-8");
}
}
进行第三方接口测试
controller层:
package com.qyq.springbootapi.controller;
import com.alibaba.fastjson.JSON;
import com.qyq.springbootapi.result.ResponseResult;
import com.qyq.springbootapi.util.AesUtil;
import com.qyq.springbootapi.util.RsaUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* 使用RSA加密AES密钥,然后用AES加密数据进行传输
* 非对称算法加解密速度慢,对称算法快。so....
*/
@RestController
public class AESController {
@Autowired
private RestTemplate restTemplate;
@Value("${RSA.publicKey}")
private String publicKey;
@Value("${RSA.privateKey}")
private String privateKey;
@GetMapping("/server")
public ResponseResult TestApiController(@RequestParam("desKey") String desKey,
@RequestParam("data") String data){
try {
String des_key = URLDecoder.decode(desKey, "UTF-8");
String r_data = URLDecoder.decode(data, "UTF-8");
System.out.println("接收到的加密AES密钥:"+des_key);
System.out.println("接收到的加密数据:"+r_data);
//先用RSA私钥解密得到AES密钥
String decrypt = RsaUtil.decrypt(des_key, privateKey);
System.out.println("解密后得到的AES密钥:"+decrypt);
//再使用AES密钥解密数据
String s = AesUtil.decrypt(r_data, decrypt);
System.out.println("AES密钥解密后的数据:"+s);
//加签返回信息
String sign = RsaUtil.sign(s, privateKey);
return new ResponseResult(0,"成功",sign);
} catch (Exception e) {
e.printStackTrace();
return new ResponseResult(0,"失败",404);
}
}
@GetMapping("/client")
public ResponseResult TestApiController1(String content){
try {
//生成AES随机密钥
String generateKey = AesUtil.getGenerateKey();
System.out.println("生成AES随机密钥:"+generateKey);
//使用RSA加密AES密钥
String desKey = RsaUtil.encrypt(generateKey, publicKey);
System.out.println("公钥加密AES密钥:"+desKey);
//AES加密数据
String data = AesUtil.encrypt(content, generateKey);
URI uri = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/server").queryParam("desKey", URLEncoder.encode(desKey,"UTF-8"))
.queryParam("data",URLEncoder.encode(data,"UTF-8")).build().toUri();
ResponseResult result = restTemplate.getForObject(uri, ResponseResult.class);
String jsonString = JSON.toJSONString(result.getData());
System.out.println("返回的签证信息:"+jsonString);
boolean verify = RsaUtil.verify(content, publicKey, jsonString);
System.out.println("验签结果:"+verify);
return new ResponseResult(0,"成功",verify);
} catch (Exception e) {
e.printStackTrace();
return new ResponseResult(0,"失败",404);
}
}
}