How to encrypt sensitive information in configuration files in java projects

In daily development, we often write some sensitive information into the *.properties configuration file, such as database password, redis password, admin user password and even system user password.

When I do operation and maintenance in a bank, I often encounter such a situation:

The system of the bank is managed through the bastion machine. In theory, the application administrator should not know the password of any system user. Only through the bastion machine, the user can log in to the corresponding user with a read-only key or a writable key. However, when I checked the configuration file of the application occasionally, I found that the application needs to log in to the system user when calling the CD, and the user name and password are written in the configuration file in clear text. Knowing the username and password, you can use the su command to switch users at will. There are also database passwords, etc., which can be found in the configuration file, which has great hidden dangers in terms of information security and permission control.

Therefore, for security reasons, it is necessary to encrypt sensitive information in the configuration file.

Not much to say, go directly to the method:

  1. 重写PropertyPlaceholderConfigurer 
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.MissingResourceException;
    import java.util.Properties;
    
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
    
    
    public final class PropertiesUtil extends PropertyPlaceholderConfigurer {
        private static final byte[] KEY = {9, -1, 0, 5, 39, 8, 6, 19};
        private static Map<String, String> ctxPropertiesMap;
        private List<String> decryptProperties;
    
        @Override
        protected void loadProperties(Properties props) throws IOException {
            super.loadProperties(props);
            ctxPropertiesMap = new HashMap<String, String>();
            for (Object key : props.keySet()) {
                String keyStr = key.toString();
                String value = props.getProperty(keyStr);
                if (decryptProperties != null && decryptProperties.contains(keyStr)) {
                    value = SecurityUtil.decryptDes(value, KEY);
                    props.setProperty(keyStr, value);
                }
                ctxPropertiesMap.put(keyStr, value);
            }
        }
    
        /**
         * @param decryptPropertiesMap the decryptPropertiesMap to set
         */
        public void setDecryptProperties(List<String> decryptProperties) {
            this.decryptProperties = decryptProperties;
        }
    
        /**
         * Get a value based on key , if key does not exist , null is returned
         *
         * @param key
         * @return
         */
        public static String getString(String key) {
            try {
                return ctxPropertiesMap.get(key);
            } catch (MissingResourceException e) {
                return null;
            }
        }
    
        /**
         * Get the value according to the key
         *
         * @param key
         * @return
         */
        public static int getInt(String key) {
            return Integer.parseInt(ctxPropertiesMap.get(key));
        }
    
        /**
         * Get the value according to the key
         *
         * @param key
         * @param defaultValue
         * @return
         */
        public static int getInt(String key, int defaultValue) {
            String value = ctxPropertiesMap.get(key);
            if (StringUtils.isBlank(value)) {
                return defaultValue;
            }
            return Integer.parseInt(value);
        }
    
        /**
         * Get the value according to the key
         * @param key
         * @param defaultValue
         * @return
         */
        public static boolean getBoolean(String key, boolean defaultValue) {
            String value = ctxPropertiesMap.get(key);
            if (StringUtils.isBlank(value)) {
                return defaultValue;
            }
            return new Boolean(value);
        }
    
        public static void main(String[] args) {
            String encrypt = SecurityUtil.encryptDes("ROOT", KEY);
            System.out.println(encrypt);
            System.out.println(SecurityUtil.decryptDes(encrypt, KEY));
        }
    }
    
     
    public final class SecurityUtil {
    	private SecurityUtil() {
    	}
    
    	public static final String CHARSET = "UTF-8";
    
    	/**
    	 * BASE64 decoding
    	 *
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static final byte[] decryptBASE64(String key) {
    		try {
    			return new BASE64Encoder().decode(key);
    		} catch (Exception e) {
    			throw new RuntimeException("Decryption error, error message: ", e);
    		}
    	}
    
    	/**
    	 * BASE64编码
    	 * 
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static final String encryptBASE64(byte[] key) {
    		try {
    			return new BASE64Encoder().encode(key);
    		} catch (Exception e) {
    			throw new RuntimeException("加密错误,错误信息:", e);
    		}
    	}
    
    
    	/**
    	 * 数据解密,算法(DES)
    	 * 
    	 * @param cryptData
    	 *            加密数据
    	 * @return 解密后的数据
    	 */
    	public static final String decryptDes(String cryptData, byte[] key) {
    		String decryptedData = null;
    		try {
    			// 把字符串解码为字节数组,并解密
    			decryptedData = new String(DESCoder.decrypt(decryptBASE64(cryptData), key));
    		} catch (Exception e) {
    			throw new RuntimeException("解密错误,错误信息:", e);
    		}
    		return decryptedData;
    	}
    
    	/**
    	 * 数据加密,算法(DES)
    	 * 
    	 * @param data
    	 *            要进行加密的数据
    	 * @return 加密后的数据
    	 */
    	public static final String encryptDes(String data, byte[] key) {
    		String encryptedData = null;
    		try {
    			// 加密,并把字节数组编码成字符串
    			encryptedData = encryptBASE64(DESCoder.encrypt(data.getBytes(), key));
    		} catch (Exception e) {
    			throw new RuntimeException("加密错误,错误信息:", e);
    		}
    		return encryptedData;
    	}
    
    
    }
     
    import java.io.UnsupportedEncodingException;
    
    /**
     * Hex encoder and decoder. The charset used for certain operation can be set,
     * the default is set in
     * 
     * @author ShenHuaJie
     * @version $Id: Hex.java, v 0.1 2014年3月25日 上午9:39:07 ShenHuaJie Exp $
     */
    public class Hex {
    
    	/***
    	 * Default charset name is {@link CharEncoding#UTF_8}
    	 */
    	public static final String DEFAULT_CHARSET_NAME = "UTF-8";
    
    	/***
    	 * Used to build output as Hex
    	 */
    	private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
    			'e', 'f' };
    
    	/***
    	 * Used to build output as Hex
    	 */
    	private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
    			'E', 'F' };
    
    	/***
    	 * Converts an array of characters representing hexadecimal values into an
    	 * array of bytes of those same values. The returned array will be half the
    	 * length of the passed array, as it takes two characters to represent any
    	 * given byte. An exception is thrown if the passed char array has an odd
    	 * number of elements.
    	 * 
    	 * @param data An array of characters containing hexadecimal digits
    	 * @return A byte array containing binary data decoded from the supplied
    	 *         char array.
    	 * @throws Exception Thrown if an odd number or illegal of characters is
    	 *             supplied
    	 */
    	public static byte[] decodeHex(char[] data) throws Exception {
    
    		int len = data.length;
    
    		if ((len & 0x01) != 0) {
    			throw new Exception("Odd number of characters.");
    		}
    
    		byte[] out = new byte[len >> 1];
    
    		// two characters form the hex value.
    		for (int i = 0, j = 0; j < len; i++) {
    			int f = toDigit(data[j], j) << 4;
    			j++;
    			f = f | toDigit(data[j], j);
    			j++;
    			out[i] = (byte) (f & 0xFF);
    		}
    
    		return out;
    	}
    
    	/***
    	 * Converts an array of bytes into an array of characters representing the
    	 * hexadecimal values of each byte in order. The returned array will be
    	 * double the length of the passed array, as it takes two characters to
    	 * represent any given byte.
    	 * 
    	 * @param data a byte[] to convert to Hex characters
    	 * @return A char[] containing hexadecimal characters
    	 */
    	public static char[] encodeHex(byte[] data) {
    		return encodeHex(data, true);
    	}
    
    	/***
    	 * Converts an array of bytes into an array of characters representing the
    	 * hexadecimal values of each byte in order. The returned array will be
    	 * double the length of the passed array, as it takes two characters to
    	 * represent any given byte.
    	 * 
    	 * @param data a byte[] to convert to Hex characters
    	 * @param toLowerCase <code>true</code> converts to lowercase,
    	 *            <code>false</code> to uppercase
    	 * @return A char[] containing hexadecimal characters
    	 * @since 1.4
    	 */
    	public static char[] encodeHex(byte[] data, boolean toLowerCase) {
    		return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
    	}
    
    	/***
    	 * Converts an array of bytes into an array of characters representing the
    	 * hexadecimal values of each byte in order. The returned array will be
    	 * double the length of the passed array, as it takes two characters to
    	 * represent any given byte.
    	 * 
    	 * @param data a byte[] to convert to Hex characters
    	 * @param toDigits the output alphabet
    	 * @return A char[] containing hexadecimal characters
    	 * @since 1.4
    	 */
    	protected static char[] encodeHex(byte[] data, char[] toDigits) {
    		int l = data.length;
    		char[] out = new char[l << 1];
    		// two characters form the hex value.
    		for (int i = 0, j = 0; i < l; i++) {
    			out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
    			out[j++] = toDigits[0x0F & data[i]];
    		}
    		return out;
    	}
    
    	/***
    	 * Converts an array of bytes into a String representing the hexadecimal
    	 * values of each byte in order. The returned String will be double the
    	 * length of the passed array, as it takes two characters to represent any
    	 * given byte.
    	 * 
    	 * @param data a byte[] to convert to Hex characters
    	 * @return A String containing hexadecimal characters
    	 * @since 1.4
    	 */
    	public static String encodeHexString(byte[] data) {
    		return new String(encodeHex(data));
    	}
    
    	/***
    	 * Converts a hexadecimal character to an integer.
    	 * 
    	 * @param ch A character to convert to an integer digit
    	 * @param index The index of the character in the source
    	 * @return An integer
    	 * @throws Exception Thrown if ch is an illegal hex character
    	 */
    	protected static int toDigit(char ch, int index) throws Exception {
    		int digit = Character.digit(ch, 16);
    		if (digit == -1) {
    			throw new Exception("Illegal hexadecimal charcter " + ch + " at index " + index);
    		}
    		return digit;
    	}
    
    	private static String charsetName = DEFAULT_CHARSET_NAME;
    
    	/***
    	 * Creates a new codec with the default charset name
    	 * {@link #DEFAULT_CHARSET_NAME}
    	 */
    	public Hex() {
    	}
    
    	/***
    	 * Creates a new codec with the given charset name.
    	 * 
    	 * @param csName the charset name.
    	 * @since 1.4
    	 */
    	public Hex(String csName) {
    		charsetName = csName;
    	}
    
    	/***
    	 * Converts an array of character bytes representing hexadecimal values into
    	 * an array of bytes of those same values. The returned array will be half
    	 * the length of the passed array, as it takes two characters to represent
    	 * any given byte. An exception is thrown if the passed char array has an
    	 * odd number of elements.
    	 * 
    	 * @param array An array of character bytes containing hexadecimal digits
    	 * @return A byte array containing binary data decoded from the supplied
    	 *         byte array (representing characters).
    	 * @throws Exception Thrown if an odd number of characters is supplied to
    	 *             this function
    	 * @see #decodeHex(char[])
    	 */
    	public byte[] decode(byte[] array) throws Exception {
    		try {
    			return decodeHex(new String(array, getCharsetName()).toCharArray());
    		} catch (Exception e) {
    			throw new Exception(e.getMessage(), e);
    		}
    	}
    
    	/***
    	 * Converts a String or an array of character bytes representing hexadecimal
    	 * values into an array of bytes of those same values. The returned array
    	 * will be half the length of the passed String or array, as it takes two
    	 * characters to represent any given byte. An exception is thrown if the
    	 * passed char array has an odd number of elements.
    	 * 
    	 * @param object A String or, an array of character bytes containing
    	 *            hexadecimal digits
    	 * @return A byte array containing binary data decoded from the supplied
    	 *         byte array (representing characters).
    	 * @throws Exception Thrown if an odd number of characters is supplied to
    	 *             this function or the object is not a String or char[]
    	 * @see #decodeHex(char[])
    	 */
    	public Object decode(Object object) throws Exception {
    		try {
    			char[] charArray = object instanceof String ? ((String) object).toCharArray() : (char[]) object;
    			return decodeHex(charArray);
    		} catch (ClassCastException e) {
    			throw new Exception(e.getMessage(), e);
    		}
    	}
    
    	/***
    	 * Converts an array of bytes into an array of bytes for the characters
    	 * representing the hexadecimal values of each byte in order. The returned
    	 * array will be double the length of the passed array, as it takes two
    	 * characters to represent any given byte.
    	 * <p>
    	 * The conversion from hexadecimal characters to the returned bytes is
    	 * performed with the charset named by {@link #getCharsetName()}.
    	 * </p>
    	 * 
    	 * @param array a byte[] to convert to Hex characters
    	 * @return A byte[] containing the bytes of the hexadecimal characters
    	 * @throws IllegalStateException if the charsetName is invalid. This API
    	 *             throws {@link IllegalStateException} instead of
    	 *             {@link Exception} for backward compatibility.
    	 * @see #encodeHex(byte[])
    	 */
    	public static byte[] encode(byte[] array) throws UnsupportedEncodingException {
    		String string = encodeHexString(array);
    		if (string == null) {
    			return null;
    		}
    		return string.getBytes(charsetName);
    	}
    
    	/***
    	 * Converts a String or an array of bytes into an array of characters
    	 * representing the hexadecimal values of each byte in order. The returned
    	 * array will be double the length of the passed String or array, as it
    	 * takes two characters to represent any given byte.
    	 * <p>
    	 * The conversion from hexadecimal characters to bytes to be encoded to
    	 * performed with the charset named by {@link #getCharsetName()}.
    	 * </p>
    	 * 
    	 * @param object a String, or byte[] to convert to Hex characters
    	 * @return A char[] containing hexadecimal characters
    	 * @throws Exception Thrown if the given object is not a String or byte[]
    	 * @see #encodeHex(byte[])
    	 */
    	public Object encode(Object object) throws Exception {
    		try {
    			byte[] byteArray = object instanceof String ? ((String) object).getBytes(getCharsetName())
    					: (byte[]) object;
    			return encodeHex(byteArray);
    		} catch (ClassCastException e) {
    			throw new Exception(e.getMessage(), e);
    		} catch (Exception e) {
    			throw new Exception(e.getMessage(), e);
    		}
    	}
    
    	/***
    	 * Gets the charset name.
    	 * 
    	 * @return the charset name.
    	 * @since 1.4
    	 */
    	public String getCharsetName() {
    		return charsetName;
    	}
    
    	/***
    	 * Returns a string representation of the object, which includes the charset
    	 * name.
    	 * 
    	 * @return a string representation of the object.
    	 */
    	@Override
    	public String toString() {
    		return super.toString() + "[charsetName=" + charsetName + "]";
    	}
    }
    
     
    import java.security.MessageDigest;
    
    /**
     * MD加密组件
     * 
     * @author du
     * @version 1.0
     * @since 1.0
     */
    public abstract class MDCoder {
    
    	/**
    	 * MD2加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static byte[] encodeMD2(byte[] data) throws Exception {
    		// 初始化MessageDigest
    		MessageDigest md = MessageDigest.getInstance("MD2");
    		// 执行消息摘要
    		return md.digest(data);
    	}
    
    	/**
    	 * MD4加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static byte[] encodeMD4(byte[] data) throws Exception {
    		// 初始化MessageDigest
    		MessageDigest md = MessageDigest.getInstance("MD4");
    		// 执行消息摘要
    		return md.digest(data);
    	}
    
    	/**
    	 * MD5加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static byte[] encodeMD5(byte[] data) throws Exception {
    		// 初始化MessageDigest
    		MessageDigest md = MessageDigest.getInstance("MD5");
    		// 执行消息摘要
    		return md.digest(data);
    	}
    
    	/**
    	 * Tiger加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static byte[] encodeTiger(byte[] data) throws Exception {
    		// 初始化MessageDigest
    		MessageDigest md = MessageDigest.getInstance("Tiger");
    		// 执行消息摘要
    		return md.digest(data);
    	}
    
    	/**
    	 * TigerHex加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static String encodeTigerHex(byte[] data) throws Exception {
    		// 执行消息摘要
    		byte[] b = encodeTiger(data);
    		// 做十六进制编码处理
    		return new String(Hex.encode(b));
    	}
    
    	/**
    	 * Whirlpool加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static byte[] encodeWhirlpool(byte[] data) throws Exception {
    		// 初始化MessageDigest
    		MessageDigest md = MessageDigest.getInstance("Whirlpool");
    		// 执行消息摘要
    		return md.digest(data);
    	}
    
    	/**
    	 * WhirlpoolHex加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static String encodeWhirlpoolHex(byte[] data) throws Exception {
    		// 执行消息摘要
    		byte[] b = encodeWhirlpool(data);
    		// 做十六进制编码处理
    		return new String(Hex.encode(b));
    	}
    
    	/**
    	 * GOST3411加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static byte[] encodeGOST3411(byte[] data) throws Exception {
    		// 初始化MessageDigest
    		MessageDigest md = MessageDigest.getInstance("GOST3411");
    		// 执行消息摘要
    		return md.digest(data);
    	}
    
    	/**
    	 * GOST3411Hex加密
    	 * 
    	 * @param data 待加密数据
    	 * @return byte[] 消息摘要
    	 * @throws Exception
    	 */
    	public static String encodeGOST3411Hex(byte[] data) throws Exception {
    		// 执行消息摘要
    		byte[] b = encodeGOST3411(data);
    		// 做十六进制编码处理
    		return new String(Hex.encode(b));
    	}
    }
    
     
    import java.security.InvalidKeyException;
    import java.security.Key;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.spec.InvalidKeySpecException;
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.KeyGenerator;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    
    /**
     * DES安全编码组件
     * 
     * @author du
     * @version 1.0
     * @since 1.0
     */
    public abstract class DESCoder {
    
    	/**
    	 * 密钥算法 <br>
    	 * Java 6 只支持56bit密钥 <br>
    	 * Bouncy Castle 支持64bit密钥
    	 */
    	public static final String KEY_ALGORITHM = "DES";
    
    	/**
    	 * 加密/解密算法 / 工作模式 / 填充方式
    	 */
    	public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5PADDING";
    
    	/**
    	 * 转换密钥
    	 * 
    	 * @param key 二进制密钥
    	 * @return Key 密钥
    	 * @throws InvalidKeyException
    	 * @throws NoSuchAlgorithmException
    	 * @throws InvalidKeySpecException
    	 * @throws Exception
    	 */
    	private static Key toKey(byte[] key) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
    		// 实例化DES密钥材料
    		DESKeySpec dks = new DESKeySpec(key);
    		// 实例化秘密密钥工厂
    		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
    		// 生成秘密密钥
    		SecretKey secretKey = keyFactory.generateSecret(dks);
    		return secretKey;
    	}
    
    	/**
    	 * 解密
    	 * 
    	 * @param data 待解密数据
    	 * @param key 密钥
    	 * @return byte[] 解密数据
    	 * @throws InvalidKeySpecException
    	 * @throws NoSuchAlgorithmException
    	 * @throws InvalidKeyException
    	 * @throws NoSuchPaddingException
    	 * @throws BadPaddingException
    	 * @throws IllegalBlockSizeException
    	 * @throws Exception
    	 */
    	public static byte[] decrypt(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException,
    			InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
    		// 还原密钥
    		Key k = toKey(key);
    		// 实例化
    		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
    		// 初始化,设置为解密模式
    		cipher.init(Cipher.DECRYPT_MODE, k);
    		// 执行操作
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * 加密
    	 * 
    	 * @param data 待加密数据
    	 * @param key 密钥
    	 * @return byte[] 加密数据
    	 * @throws NoSuchPaddingException
    	 * @throws NoSuchAlgorithmException
    	 * @throws InvalidKeyException
    	 * @throws BadPaddingException
    	 * @throws IllegalBlockSizeException
    	 * @throws InvalidKeySpecException
    	 * @throws Exception
    	 */
    	public static byte[] encrypt(byte[] data, byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException,
    			InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException {
    		// 还原密钥
    		Key k = toKey(key);
    		// 实例化
    		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
    		// 初始化,设置为加密模式
    		cipher.init(Cipher.ENCRYPT_MODE, k);
    		// 执行操作
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * 生成密钥 <br>
    	 * Java 6 只支持56bit密钥 <br>
    	 * Bouncy Castle 支持64bit密钥 <br>
    	 * 
    	 * @return byte[] 二进制密钥
    	 * @throws NoSuchAlgorithmException
    	 * @throws Exception
    	 */
    	public static byte[] initKey() throws NoSuchAlgorithmException {
    		/*
    		 * 实例化密钥生成器
    		 * 
    		 * 若要使用64bit密钥注意替换 将下述代码中的KeyGenerator.getInstance(CIPHER_ALGORITHM);
    		 * 替换为KeyGenerator.getInstance(CIPHER_ALGORITHM, "BC");
    		 */
    		KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
    		/*
    		 * 初始化密钥生成器 若要使用64bit密钥注意替换 将下述代码kg.init(56); 替换为kg.init(64);
    		 */
    		kg.init(56, new SecureRandom());
    		// 生成秘密密钥
    		SecretKey secretKey = kg.generateKey();
    		// 获得密钥的二进制编码形式
    		return secretKey.getEncoded();
    	}
    }
    
     
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.PushbackInputStream;
    
    /**
     * 密码器类
     * 
     * @author du
     * @since 2017-11-19
     */
    public class BASE64Encoder {
    
        /**
         * 译码数据源
         */
        private static final char[] PEM_ARRAY = {
            // 0  1   2   3    4    5    6    7
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', // 0
            'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', // 1
            'q', 'r', 's', 't', 'u', 'v', 'w', 'x', // 2
            'y', 'z', '1', '2', '3', '4', '5', '6', // 3
            '7', '8', '9', '0', 'A', 'B', 'C', 'D', // 4
            'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', // 5
            'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', // 6
            'U', 'V', 'W', 'X', 'Y', 'Z', '+', '/' // 7
        };
    
        private static final byte[] pem_convert_array = new byte[256];
    
        private byte[] decode_buffer = new byte[4];
    
        public BASE64Encoder() {
        }
    
        /**
         * 编码
         */
        public String encode(byte[] bt) {
            int totalBits = bt.length * 8;
            int nn = totalBits % 6;
            int curPos = 0;// process bits
            StringBuilder toReturn = new StringBuilder(32);
            while (curPos < totalBits) {
                int bytePos = curPos / 8;
                switch (curPos % 8) {
                case 0:
                    toReturn.append(PEM_ARRAY[(bt[bytePos] & 0xfc) >> 2]);
                    break;
                case 2:
                    toReturn.append(PEM_ARRAY[(bt[bytePos] & 0x3f)]);
                    break;
                case 4:
                    if (bytePos == bt.length - 1) {
                        toReturn.append(PEM_ARRAY[((bt[bytePos] & 0x0f) << 2) & 0x3f]);
                    } else {
                        int pos = (((bt[bytePos] & 0x0f) << 2) | ((bt[bytePos + 1] & 0xc0) >> 6)) & 0x3f;
                        toReturn.append(PEM_ARRAY[pos]);
                    }
                    break;
                case 6:
                    if (bytePos == bt.length - 1) {
                        toReturn.append(PEM_ARRAY[((bt[bytePos] & 0x03) << 4) & 0x3f]);
                    } else {
                        int pos = (((bt[bytePos] & 0x03) << 4) | ((bt[bytePos + 1] & 0xf0) >> 4)) & 0x3f;
                        toReturn.append(PEM_ARRAY[pos]);
                    }
                    break;
                default:
                    break;
                }
                curPos += 6;
            }
            if (nn == 2) {
                toReturn.append("==");
            } else if (nn == 4) {
                toReturn.append("=");
            }
            return toReturn.toString();
        }
    
        /**
         * 解码
         */
        public byte[] decode(String str) throws IOException {
            byte[] arrayOfByte = str.getBytes();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(arrayOfByte);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            decodeBuffer(inputStream, outputStream);
            return outputStream.toByteArray();
        }
    
        private void decodeBuffer(InputStream paramInputStream, OutputStream paramOutputStream) throws IOException {
            PushbackInputStream localPushbackInputStream = new PushbackInputStream(paramInputStream);
            int j = 0;
            while (true) {
                try {
                    int k = bytesPerLine();
                    int i = 0;
                    if (i + bytesPerAtom() < k) {
                        decodeAtom(localPushbackInputStream, paramOutputStream, bytesPerAtom());
                        j += bytesPerAtom();
                        i += bytesPerAtom();
                        continue;
                    }
    
                    if (i + bytesPerAtom() == k) {
                        decodeAtom(localPushbackInputStream, paramOutputStream, bytesPerAtom());
                        j += bytesPerAtom();
                    } else {
                        decodeAtom(localPushbackInputStream, paramOutputStream, k - i);
                        j += k - i;
                    }
                } catch (RuntimeException e) {
                    String.valueOf(j);
                    break;
                }
            }
        }
    
        private int bytesPerAtom() {
            return 4;
        }
    
        private int bytesPerLine() {
            return 72;
        }
    
        private void decodeAtom(PushbackInputStream paramPushbackInputStream, OutputStream paramOutputStream, int paramInt)
            throws IOException {
            int i;
            int j = -1;
            int k = -1;
            int m = -1;
            int n = -1;
    
            if (paramInt < 2) {
                throw new java.lang.ArrayStoreException("BASE64Decoder: Not enough bytes for an atom.");
            }
            do {
                i = paramPushbackInputStream.read();
                if (i == -1) {
                    throw new RuntimeException();
                }
            } while ((i == 10) || (i == 13));
            this.decode_buffer[0] = (byte)i;
    
            i = readFully(paramPushbackInputStream, this.decode_buffer, 1, paramInt - 1);
            if (i == -1) {
                throw new RuntimeException();
            }
    
            if ((paramInt > 3) && (this.decode_buffer[3] == 61)) {
                paramInt = 3;
            }
            if ((paramInt > 2) && (this.decode_buffer[2] == 61)) {
                paramInt = 2;
            }
            switch (paramInt) {
            case 4:
                n = pem_convert_array[(this.decode_buffer[3] & 0xFF)];
            case 3:
                m = pem_convert_array[(this.decode_buffer[2] & 0xFF)];
            case 2:
                k = pem_convert_array[(this.decode_buffer[1] & 0xFF)];
                j = pem_convert_array[(this.decode_buffer[0] & 0xFF)];
            }
    
            switch (paramInt) {
            case 2:
                paramOutputStream.write((byte)(j << 2 & 0xFC | k >>> 4 & 0x3));
                break;
            case 3:
                paramOutputStream.write((byte)(j << 2 & 0xFC | k >>> 4 & 0x3));
                paramOutputStream.write((byte)(k << 4 & 0xF0 | m >>> 2 & 0xF));
                break;
            case 4:
                paramOutputStream.write((byte)(j << 2 & 0xFC | k >>> 4 & 0x3));
                paramOutputStream.write((byte)(k << 4 & 0xF0 | m >>> 2 & 0xF));
                paramOutputStream.write((byte)(m << 6 & 0xC0 | n & 0x3F));
            }
        }
    
        private int readFully(InputStream paramInputStream, byte[] paramArrayOfByte, int paramInt1, int paramInt2)
            throws IOException {
            for (int i = 0; i < paramInt2; i++) {
                int j = paramInputStream.read();
                if (j == -1) {
                    return i == 0 ? -1 : i;
                }
                paramArrayOfByte[(i + paramInt1)] = (byte)j;
            }
            return paramInt2;
        }
    
        static {
            for (int i = 0; i < 255; i++) {
                pem_convert_array[i] = -1;
            }
            for (int i = 0; i < PEM_ARRAY.length; i++)
                pem_convert_array[PEM_ARRAY[i]] = (byte)i;
        }
    }
    
     
  2. 加密敏感信息:

    执行PropertiesUtil类中的main方法:

        public static void main(String[] args) {//ROOT为要加密的明文
            String encrypt = SecurityUtil.encryptDes("ROOT", KEY);
            System.out.println(encrypt);
            System.out.println(SecurityUtil.decryptDes(encrypt, KEY));
        }
     此处加密数据库密码,假设数据库密码为ROOT

     

  3. 配置文件中该明文为密文:
    db.writer.username=root
    db.writer.password=9u7x63ZJmcy=
     
  4. 在spring配置文件中引入配置:
    	<!-- 引入属性文件 -->
    	<bean class="com.ds.core.util.PropertiesUtil">
    		<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    		<property name="ignoreResourceNotFound" value="true" />
    		<property name="locations">
    			<list>
    				<value>classpath:config/jdbc.properties</value>
    			</list>
    		</property>
    		<property name="decryptProperties">
    			<array>
    				<!-- 需要解密的配置 -->
    				<value>db.writer.password</value>
    			</array>
    		</property>
    	</bean>
     

 搞定!酷

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326306238&siteId=291194637