java项目中,如何加密配置文件中的敏感信息

时间:2021-02-12 11:23:53

在日常开发中,我们常常会把一些敏感信息写进*.properties配置文件中,比如数据库密码、redis密码、admin用户的密码甚至系统用户的密码等。

我在某银行做运维时,经常会遇到这样的情况:

银行的系统都是通过堡垒机管理的,应用管理人员理论上不应该知道任何系统用户的密码,只需通过堡垒机,使用只读key或可写key即可登录相应的用户。但在一次偶尔查看应用的配置文件时,我发现应用在调用CD时需要登录系统用户,而用户名和密码均使用明文写在了配置文件中。知道了用户名密码,就可以使用su命令随意切换用户了。诸如此类的还有数据库密码等,均可在配置文件中找到,这在信息安全和权限控制等方面有很大的隐患。

所以出于安全考虑,对配置文件中敏感信息的加密就很有必要了。

不多说了,直接上方法:

  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;
    }
    }

    /**
    * 根据key获取值
    *
    * @param key
    * @return
    */
    public static int getInt(String key) {
    return Integer.parseInt(ctxPropertiesMap.get(key));
    }

    /**
    * 根据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);
    }

    /**
    * 根据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解码
    *
    * @param key
    * @return
    * @throws Exception
    */
    public static final byte[] decryptBASE64(String key) {
    try {
    return new BASE64Encoder().decode(key);
    } catch (Exception e) {
    throw new RuntimeException("解密错误,错误信息:", 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>
     

 搞定!java项目中,如何加密配置文件中的敏感信息