Skip to content

Commit

Permalink
sensitive info encrypt
Browse files Browse the repository at this point in the history
Signed-off-by: kakawu <[email protected]>
  • Loading branch information
wgcitgkaka committed Apr 5, 2023
1 parent 0f64d1f commit 4a45421
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 50 deletions.
12 changes: 12 additions & 0 deletions src/main/java/com/webank/ai/fate/board/services/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.webank.ai.fate.board.services;

import com.webank.ai.fate.board.pojo.UserDTO;
import com.webank.ai.fate.board.utils.StandardRSAUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -63,6 +65,16 @@ public boolean checkUser(String username, String password) {
updateConfig();
String usernameValue = getValue("server.board.login.username");
String passwordValue = getValue("server.board.login.password");
String privateKey = getValue("server.board.encrypt.private_key");
String encrypted = getValue("server.board.encrypt.enable");
if (StringUtils.isNotBlank(privateKey) && "true".equalsIgnoreCase(encrypted)) {
try {
passwordValue = StandardRSAUtils.decryptByPrivateKey(passwordValue, privateKey);
} catch (Exception e) {
logger.error("decrypt password error");
return false;
}
}

if (!username.equals(usernameValue)) {
return false;
Expand Down
328 changes: 278 additions & 50 deletions src/main/java/com/webank/ai/fate/board/utils/StandardRSAUtils.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.webank.ai.fate.board.utils;

import org.apache.commons.codec.binary.Base64;

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;

Expand All @@ -15,69 +16,296 @@
*/
public class StandardRSAUtils {

private static Map<Integer, String> keyMap = new HashMap<>();
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";

/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

/**
* 获取公钥的key
*/
private static final String PUBLIC_KEY = "RSAPublicKey";

/**
* 获取私钥的key
*/
private static final String PRIVATE_KEY = "RSAPrivateKey";

/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 245;

/**
* 随机生成密钥对
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 256;

/**
* <p>
* 生成密钥对(公钥和私钥)
* </p>
*
* @throws NoSuchAlgorithmException
* @return
* @throws Exception
*/
public static void getKeyPair() throws Exception {
//KeyPairGenerator类用于生成公钥和密钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048, new SecureRandom());
//生成一个密钥对,保存在keyPair中
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(2048);
KeyPair keyPair = keyPairGen.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();//得到私钥
PublicKey publicKey = keyPair.getPublic();//得到公钥
//得到公钥字符串
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
//得到私钥字符串
String privateKeyString = new String(Base64.encodeBase64(privateKey.getEncoded()));
//将公钥和私钥保存到Map
keyMap.put(0, publicKeyString);//0表示公钥
keyMap.put(1, privateKeyString);//1表示私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}

/**
* RSA公钥加密
* <p>
* 用私钥对信息生成数字签名
* </p>
*
* @param str 加密字符串
* @param publicKey 公钥
* @return 密文
* @throws Exception 加密过程中的异常信息
* @param msg 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static String encrypt(String str, String publicKey) throws Exception {
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(decoded));
//RAS加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
public static String sign(String msg, String privateKey) throws Exception {
byte[] data = msg.getBytes();
byte[] keyBytes = Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateK);
signature.update(data);
return Base64.getEncoder().encodeToString(signature.sign());
}

/**
* RSA私钥解密
* <p>
* 校验数字签名
* </p>
*
* @param str 加密字符串
* @param privateKey 私钥
* @return 铭文
* @throws Exception 解密过程中的异常信息
* @param msg 已加密数据
* @param publicKey 公钥(BASE64编码)
* @param sign 数字签名
* @return
* @throws Exception
*/
public static String decrypt(String str, String privateKey) throws Exception {
//Base64解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
//Base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
public static boolean verify(String msg, String publicKey, String sign)
throws Exception {
byte[] data = msg.getBytes();
byte[] keyBytes = Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicK = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicK);
signature.update(data);
return signature.verify(Base64.getDecoder().decode(sign));
}

/**
* <P>
* 私钥解密
* </p>
*
* @param encryptedDataStr 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String encryptedDataStr, String privateKey)
throws Exception {
byte[] encryptedData = Base64.getDecoder().decode(encryptedDataStr);
byte[] keyBytes = Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.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(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, 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);
}

/**
* <p>
* 公钥解密
* </p>
*
* @param encryptedDataStr 已加密数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static String decryptByPublicKey(String encryptedDataStr, String publicKey)
throws Exception {
byte[] encryptedData = Base64.getDecoder().decode(encryptedDataStr);
byte[] keyBytes = Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.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(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, 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);
}

/**
* <p>
* 公钥加密
* </p>
*
* @param msg 源数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String msg, String publicKey)
throws Exception {
byte[] data = msg.getBytes();
byte[] keyBytes = Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.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, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();

String encryptedDataStr = Base64.getEncoder().encodeToString(encryptedData);
return encryptedDataStr;
}

/**
* <p>
* 私钥加密
* </p>
*
* @param msg 源数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static String encryptByPrivateKey(String msg, String privateKey)
throws Exception {
byte[] data = msg.getBytes();
byte[] keyBytes = Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.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, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();

String encryptedDataStr = Base64.getEncoder().encodeToString(encryptedData);
return encryptedDataStr;
}

/**
* <p>
* 获取私钥
* </p>
*
* @param keyMap 密钥对
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64.getEncoder().encodeToString(key.getEncoded());
}

/**
* <p>
* 获取公钥
* </p>
*
* @param keyMap 密钥对
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64.getEncoder().encodeToString(key.getEncoded());
}


}
2 changes: 2 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ server.compression.enabled=true
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain
server.board.login.username=admin
server.board.login.password=admin
server.board.encrypt.private_key=
server.board.encrypt.enable=false
#only [h,m,s] is available
server.servlet.session.timeout=4h
server.servlet.session.cookie.max-age=4h
Expand Down

0 comments on commit 4a45421

Please sign in to comment.