公司漏洞检测,检测到 线上的jar包中配置文件里面数据库密码 ,redis密码等等配置都是明文,所以需要在配置文件中加密。所以为了实现该功能直接贴代码
贴一下原作者的git(原文章忘记在哪里了),感谢大佬
https://gitee.com/pychfarm_admin/encryption/tree/main
这里定义加密,解密方法,同时配置公钥,私钥
public class MyEncryptUtil {
public static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBOkkkvjbOQ6UTCo8U4bRC/EcEtxz8haHg6lueM3NBbH3eIT7kfwQFOqj1h1qPGcQNeyn4vxzMWBAKzSQehjqVBL7/8GN7EZ7TEaUuWO+8qsuZnOdrztX7bNKACnks+SelmtbrbnFKUMAq2c2mS0o1V6iwyRxJYLGaHGXnz4KSkwIDAQAB";
public static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIE6SSS+Ns5DpRMKjxThtEL8RwS3HPyFoeDqW54zc0Fsfd4hPuR/BAU6qPWHWo8ZxA17Kfi/HMxYEArNJB6GOpUEvv/wY3sRntMRpS5Y77yqy5mc52vO1fts0oAKeSz5J6Wa1utucUpQwCrZzaZLSjVXqLDJHElgsZocZefPgpKTAgMBAAECgYAFaCDjTqoQWzgu4cQ2xXK7Ur7N7bNixVyOgn+u0MxDsnxZrN5qxP2wElI7Y5xgXF2diseoxqY3zn9tVEPsmwUcY73naoosx9V8oExgT/BUkZYIzj1ei08zOr984zl3dbFcxOCRvqywXj9FAAGx1mhmCzFCIauJg3aX0S9mt5/CwQJBAMYZsmMQ9owoXZuSclKVRfMHFpAPhQlcBM4xadhX0IRYATgNTxpESmcCoGWvyw3bvieNJyC9Njx6X4FJ2EZUzhECQQCm/2IM5MlsCwyKtME5RPFna2hSqYU80UzkNfDIyMokcU2JUI4Fhigog4ol0GFMiMBsHIjS+cJiAwNbIsq5rsJjAkA94yVBobkETFACHBwvBIdXxy0bUF3lcKPnrrQ8bCKuVbf7xNyjfhYoXD+zxNmQuMeNH6HLrpDVD/3qLCGuxyuhAkAiLPl/8gJWnhw+9qbkdXuB0rVS1WZy/9JgkblpHc5gjt9zTo0CDGaDhAftnSuMYiAe/+fwZTSmoj85k3ExdtZJAkEArJuG/NWY9HP4p7jtZX9rMokyB3517v7HQdJKBDIlOzseRC/roCvU8LQ/URDFBUqXCRgedxgW+0ZmKFf4xeawqw==";
public static void main(String[] args) throws Exception {
String message = "jfyt_1234";
System.out.println("原始字符串: " + message);
String messageEn = encrypt(message, PUBLIC_KEY);
System.out.println("加密后的字符串为: " + messageEn);
String messageDe = decrypt(messageEn, PRIVATE_KEY);
System.out.println("还原后的字符串为: " + messageDe);
}
public static void generateKey() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024, new SecureRandom());
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())));
System.out.println("当前生成的公钥= " + publicKeyString);
System.out.println("当前生成的私钥= " + privateKeyString);
}
public static String encrypt(String str, String publicKey) throws NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException {
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
}
public static String decrypt(String str, String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
return new String(cipher.doFinal(inputByte));
}
}
这里定义异常信息
public class PrivateKeyFindError extends Exception{
public PrivateKeyFindError() {
super();
}
public PrivateKeyFindError(String message) {
super(message);
}
public PrivateKeyFindError(String message, Throwable cause) {
super(message, cause);
}
public PrivateKeyFindError(Throwable cause) {
super(cause);
}
protected PrivateKeyFindError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
这里 我们获取配置文件中的加密配置,然后解密,主要通过前缀后缀的修改
public class EnableEncryptionData implements BeanFactoryPostProcessor, Ordered {
public static final String PREFIX_PROPERTY = "encryption.prefix";
public static final String SUFFIX_PROPERTY = "encryption.suffix";
public static final String RSA_PUBLIC_KEY_PROPERTY = "encryption.rsa.publicKey";
public static final String RSA_PRIVATE_KEY_PROPERTY = "encryption.rsa.privateKey";
public static final String DEFAULT_PREFIX = "PWD[";
public static final String DEFAULT_SUFFIX = "]";
public static final String HF_PRIVATE_KEY_PATH = "hf_private_key";
private static final Logger LOG = LoggerFactory.getLogger(EnableEncryptionData.class);
private static final Properties properties = new Properties();
private final ConfigurableEnvironment environment;
private String prefix;
private String suffix;
private String privateKey;
public EnableEncryptionData(ConfigurableEnvironment environment) {
this.environment = environment;
}
@SneakyThrows
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
MutablePropertySources propertySources = environment.getPropertySources();
for (PropertySource<?> propertySource : propertySources) {
if (propertySource.getSource() instanceof Map) {
Map<String, Object> source = (Map) propertySource.getSource();
for (String key : source.keySet()){
String property = environment.getProperty(key);
if(hasPreAndSuf(property)) {
Map<String, Object> properties = new HashMap<>();
String relay = splitPreAndSuf(property, this.prefix, this.suffix);
String decrypt = MyEncryptUtil.decrypt(relay, getPrivateKey(environment));
properties.put(key, decrypt);
propertySources.addFirst(new MapPropertySource(getRandStr(5),properties));
}
}
这里是原博客作者代码块,但是我在实际使用时发现 source.put(k, decrypt) 将解密后的配置进行写入时候,
出现了map java.lang.UnsupportedOperationException异常,主要原因是
,从配置文件中读取到的参数是只读的,不可修改,所以source.put()会抛异常,
所以改成了propertySources.addFirst(new MapPropertySource(getRandStr(5),properties));
// source.forEach((k, v) -> {
// String property = environment.getProperty(k);
// if (hasPreAndSuf(property)) {
// LOG.info("开始处理 k = [{}]", k);
// try {
// String relay = splitPreAndSuf(property, this.prefix, this.suffix);
// String decrypt = MyEncryptUtil.decrypt(relay, getPrivateKey(environment));
// source.put(k, decrypt);
// }
// catch (Exception e) {
// LOG.error("e = ", e);
// }
// }
// });
}
}
}
public static String getRandStr(int num){
String strs = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuffer buff = new StringBuffer();
for(int i=1;i<=num;i++){
char str = strs.charAt((int)(Math.random() * 26));
buff.append(str);
}
return buff.toString();
}
private String getPrivateKey(ConfigurableEnvironment environment) throws PrivateKeyFindError {
return MyEncryptUtil.PRIVATE_KEY;
// throw new PrivateKeyFindError("rsa private key is null!");
}
判断配置文件中的参数是否以我们定义的前缀后缀结尾
private boolean hasPreAndSuf(String property) {
return property.startsWith(getPrefix(environment)) && property.endsWith(getSuffix(environment));
}
protected String splitPreAndSuf(String str, String prefix, String suffix) {
return str.replace(prefix, "").replace(suffix, "");
}
private String getSuffix(ConfigurableEnvironment environment) {
this.suffix = environment.getProperty(SUFFIX_PROPERTY);
if (StringUtils.hasLength(suffix)) {
return this.suffix;
}
this.suffix = DEFAULT_SUFFIX;
return DEFAULT_SUFFIX;
}
private String getPrefix(ConfigurableEnvironment environment) {
this.prefix = environment.getProperty(PREFIX_PROPERTY);
if (StringUtils.hasLength(prefix)) {
return this.prefix;
}
this.prefix = DEFAULT_PREFIX;
return DEFAULT_PREFIX;
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE - 100;
}
static {
InputStream resource = Thread.currentThread().getContextClassLoader().getResourceAsStream(HF_PRIVATE_KEY_PATH);
try {
if (resource != null) {
properties.load(resource);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
进行启动配置
@Configuration
public class CustomerBean {
@Bean
public static EnableEncryptionData enableEncryptionData(final ConfigurableEnvironment environment) {
return new EnableEncryptionData(environment);
}
}
到这里已经完成了,接下来看一下配置文件如何使用
以PWD[为前缀,]为后缀
app.db.password=PWD[baII5Yc8yLoBudUwYI5OlclhZ41Qz34Z1b/MjEuKuhbFVlXKQ65fZQgdwMiSR+CXp/1j3aLHpAN16857H7fZxWz+iT/ldiBVNk4kn+VKQ2mBZVXnvRclXKqJ7/9YSecg1JCkmLRaHFyVjudmMXJikjtvKVIimKstYY5sdHFUqTY=]
有一点小问题,需要先将密码加密然后再进行配置,