RSA加密工具類
RsaUtils.java
package com.hahashujia.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* RSA加密解密
* @author yanan.wang
* @describe
* @createTime 2020-04-01 16:04
*/
@Slf4j
public class RsaUtils {
private static final String KEY_ALGORITHM = "RSA";
private static final int RSA_KEY_SIZE = 512;
public static void main(String[] args) throws Exception {
genKeyPair();
}
/**
* 私鑰加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
//private key
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 公鑰加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 私鑰解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 公鑰解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 隨機生成密鑰對
*
* @throws NoSuchAlgorithmException
*/
public static void genKeyPair() throws NoSuchAlgorithmException {
//KeyPairGenerator類用於生成公鑰和私鑰對,基於RSA算法生成對象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
//初始化密鑰對生成器,密鑰大小爲96-1024位
keyPairGen.initialize(RSA_KEY_SIZE, new SecureRandom());
// 生成一個密鑰對,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到私鑰
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 得到公鑰
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
// 得到私鑰字符串
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
// 將公鑰和私鑰保存到Map
log.info("公鑰加密Key:{}", publicKeyString);
log.info("私鑰解密Key:{}", privateKeyString);
Map<String, String> keyMap = new HashMap<>();
keyMap.put("publicKey", publicKeyString);
keyMap.put("publicKey", privateKeyString);
}
}
TokenService.java
package com.hahashujia.service;
import com.hahashujia.utils.RsaUtils;
import com.hahashujia.dao.ImpTokenHistoryDao;
import com.hahashujia.dao.entity.ImpTokenHistory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* EBS的Token加密/解密
* 公鑰加密/私鑰解密
*
* @author yanan.wang
* @describe
* @createTime 2020-03-13 15:52
*/
@Component
@Slf4j
public class TokenService {
@Value("${token.rsa.private_key}")
private String ebsPrivateKey;
@Value("${token.rsa.public_key}")
private String ebsPublicKey;
@Autowired
private ImpTokenHistoryDao impTokenHistoryDao;
/**
* 獲得加密字符串,加密字符不得超過53個字節</p>
* 需加密字符串:{sysCode}+時間戳+10位隨機數</p>
* 加密方式:RSA+BASE64Encoder</p>
* 時間戳:13字節
* 隨機數:10字節
*
* @param sysCode :系統CODE:最多30字節
* @return
* @throws Exception
*/
public String encryptionToken(String sysCode) {
String encodeStr = null;
try {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(sysCode)
.append(System.currentTimeMillis())
.append(randomNumber());
log.info("原文:{}, 長度:{}", stringBuffer.toString(), stringBuffer.length());
byte[] inputData = stringBuffer.toString().getBytes();
log.info("字節長度:{}", inputData.length);
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] publicKey = base64Decoder.decodeBuffer(ebsPublicKey);
byte[] encodeData = RsaUtils.encryptByPublicKey(inputData, publicKey);
BASE64Encoder base64 = new BASE64Encoder();
encodeStr = base64.encode(encodeData);
log.info("公鑰加密後:{}", encodeStr);
} catch (Exception e) {
e.printStackTrace();
}
return encodeStr;
}
/**
* check the existing token and insert a new token.
* 私鑰解密
*
* @param token
* @return
* @throws Exception
*/
public boolean validateToken(String token, String sysCode) {
try {
log.info("Token verification start.");
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] tokenByte = base64Decoder.decodeBuffer(token);
byte[] privateKey = base64Decoder.decodeBuffer(ebsPrivateKey);
byte[] decodeData = RsaUtils.decryptByPrivateKey(tokenByte, privateKey);
String result = new String(decodeData);
if (result.startsWith(sysCode)) {
String str = result.substring(sysCode.length());
long currentTime = Long.parseLong(str.substring(0, 13));
if (checkTime(currentTime)) {
//查看token是否在數據庫存在
int existTask = impTokenHistoryDao.checkToken(token);
if (existTask == 0) {
impTokenHistoryDao.insert(ImpTokenHistory.builder()
.token(token)
.systemCode(sysCode)
.build());
log.info("Token verification passed.");
return Boolean.TRUE;
} else {
log.error("Token has expired. Reason : Token already exists in database. "
+ "token :{}, sysCode:{}, decrypt token:{}",
token, sysCode, result);
}
} else {
log.error("Token has expired. Reason : Over 30 minutes. token :{}, sysCode:{}, decrypt token:{}",
token, sysCode, result);
}
} else {
log.error("Token error. Reason : Incorrect token fixed component."
+ " token :{}, sysCode:{}, decrypt token:{}",
token, sysCode, result);
}
} catch (Exception e) {
log.error("Token error or expired.", e);
}
return Boolean.FALSE;
}
/**
* 10位隨機數
*
* @return
*/
private long randomNumber() {
double temp = Math.random();
return (long) (temp * 10000000000L);
}
/**
* 校驗時間戳是否是30分鐘之內
*
* @param time
* @return 30分鐘之內返回true
*/
private boolean checkTime(long time) {
long currentTime = System.currentTimeMillis();
currentTime = currentTime - 1800000;
if (time > currentTime) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
}
Controller層調用
@ApiOperation(value = "接口描述(帶token)")
@RequestMapping(value = "token", method = RequestMethod.POST)
public ResponseEntity token(
@RequestHeader(name = "token") String token) {
if (!tokenService.validateToken(token, systemCode)) {
return ResponseEntity.badRequest().body("Token error or expired.");
}
return ResponseEntity.ok().build();
}