数据库信息 加密

配置文件中数据库信息加密思路

首先要连接数据库要明文密码,所以加密后的密文要求可逆,在连接数据库前转换为明文

准备

选取合适的加解密 摘要算法无法解密成明文所以MD5之类的不行

这里我选用的是商用国密算法(SM2)

<!--引入依赖 1.51版本可正常使用1.66版本需要修改jar-->
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.51</version>
</dependency>

在sm2包下创建Cipher.java

import java.math.BigInteger;import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
/*** * @author xsluck**/
public class Cipher {private int ct;private ECPoint p2;private SM3Digest sm3keybase;private SM3Digest sm3c3;private byte key[];private byte keyOff;public Cipher() {this.ct = 1;this.key = new byte[32];this.keyOff = 0;}@SuppressWarnings("deprecation")private void Reset() {this.sm3keybase = new SM3Digest();this.sm3c3 = new SM3Digest();byte p[] = Util.byteConvert32Bytes(p2.getX().toBigInteger());this.sm3keybase.update(p, 0, p.length);this.sm3c3.update(p, 0, p.length);p = Util.byteConvert32Bytes(p2.getY().toBigInteger());this.sm3keybase.update(p, 0, p.length);this.ct = 1;NextKey();}private void NextKey() {SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);sm3keycur.update((byte) (ct >> 24 & 0xff));sm3keycur.update((byte) (ct >> 16 & 0xff));sm3keycur.update((byte) (ct >> 8 & 0xff));sm3keycur.update((byte) (ct & 0xff));sm3keycur.doFinal(key, 0);this.keyOff = 0;this.ct++;}public ECPoint Init_enc(SM2 sm2, ECPoint userKey) {AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();BigInteger k = ecpriv.getD();ECPoint c1 = ecpub.getQ();this.p2 = userKey.multiply(k);Reset();return c1;}public void Encrypt(byte data[]) {this.sm3c3.update(data, 0, data.length);for (int i = 0; i < data.length; i++) {if (keyOff == key.length) {NextKey();}data[i] ^= key[keyOff++];}}public void Init_dec(BigInteger userD, ECPoint c1) {this.p2 = c1.multiply(userD);Reset();}public void Decrypt(byte data[]) {for (int i = 0; i < data.length; i++) {if (keyOff == key.length) {NextKey();}data[i] ^= key[keyOff++];}this.sm3c3.update(data, 0, data.length);}@SuppressWarnings("deprecation")public void Dofinal(byte c3[]) {byte p[] = Util.byteConvert32Bytes(p2.getY().toBigInteger());this.sm3c3.update(p, 0, p.length);this.sm3c3.doFinal(c3, 0);Reset();}
}

在sm2包下创建SM2.java

import java.math.BigInteger;
import java.security.SecureRandom;import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
/*** * @author xsluck**/
@SuppressWarnings("deprecation")
public class SM2 {//测试参数
/*    public static String[] ecc_param = {"8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3","787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498","63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A","8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7","421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D","0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"};*///正式参数public static String[] ecc_param = {"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF","FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC","28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93","FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123","32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7","BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"};public static SM2 Instance() {return new SM2();}public final BigInteger ecc_p;public final BigInteger ecc_a;public final BigInteger ecc_b;public final BigInteger ecc_n;public final BigInteger ecc_gx;public final BigInteger ecc_gy;public final ECCurve ecc_curve;public final ECPoint ecc_point_g;public final ECDomainParameters ecc_bc_spec;public final ECKeyPairGenerator ecc_key_pair_generator;public final ECFieldElement ecc_gx_fieldelement;public final ECFieldElement ecc_gy_fieldelement;public static ECPoint ecc_point_g_static = null;public static BigInteger ecc_p_static = null;public static BigInteger ecc_n_static = null;public SM2() {this.ecc_p = new BigInteger(ecc_param[0], 16);this.ecc_a = new BigInteger(ecc_param[1], 16);this.ecc_b = new BigInteger(ecc_param[2], 16);this.ecc_n = new BigInteger(ecc_param[3], 16);this.ecc_gx = new BigInteger(ecc_param[4], 16);this.ecc_gy = new BigInteger(ecc_param[5], 16);this.ecc_gx_fieldelement = new ECFieldElement.Fp(this.ecc_p, this.ecc_gx);this.ecc_gy_fieldelement = new ECFieldElement.Fp(this.ecc_p, this.ecc_gy);this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);ECKeyGenerationParameters ecc_ecgenparam;ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());this.ecc_key_pair_generator = new ECKeyPairGenerator();this.ecc_key_pair_generator.init(ecc_ecgenparam);}static {BigInteger ecc_p = new BigInteger(ecc_param[0], 16);ecc_p_static = ecc_p;BigInteger ecc_a = new BigInteger(ecc_param[1], 16);BigInteger ecc_b = new BigInteger(ecc_param[2], 16);ecc_n_static = new BigInteger(ecc_param[3], 16);BigInteger ecc_gx = new BigInteger(ecc_param[4], 16);BigInteger ecc_gy = new BigInteger(ecc_param[5], 16);ECFieldElement ecc_gx_fieldelement = new ECFieldElement.Fp(ecc_p, ecc_gx);ECFieldElement ecc_gy_fieldelement = new ECFieldElement.Fp(ecc_p, ecc_gy);ECCurve ecc_curve = new ECCurve.Fp(ecc_p, ecc_a, ecc_b);ecc_point_g_static = new ECPoint.Fp(ecc_curve, ecc_gx_fieldelement, ecc_gy_fieldelement);}
}

在sm2包下创建SM2Utils.java

import java.io.IOException;
import java.math.BigInteger;import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;import com.xsluck.sm2.BaseUtil;
/*** @author xsluck*/
public class SM2Utils {//生成随机秘钥对public static void generateKeyPair() {SM2 sm2 = SM2.Instance();AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();BigInteger privateKey = ecpriv.getD();ECPoint publicKey = ecpub.getQ();System.out.println("公钥: " + Util.byteToHex(publicKey.getEncoded()));System.out.println("私钥: " + Util.byteToHex(privateKey.toByteArray()));}//数据加密public static String encrypt(byte[] publicKey, byte[] data) throws IOException {if (publicKey == null || publicKey.length == 0) {return null;}if (data == null || data.length == 0) {return null;}byte[] source = new byte[data.length];System.arraycopy(data, 0, source, 0, data.length);Cipher cipher = new Cipher();SM2 sm2 = SM2.Instance();ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);ECPoint c1 = cipher.Init_enc(sm2, userKey);cipher.Encrypt(source);byte[] c3 = new byte[32];cipher.Dofinal(c3);//      System.out.println("C1 " + Util.byteToHex(c1.getEncoded()));
//      System.out.println("C2 " + Util.byteToHex(source));
//      System.out.println("C3 " + Util.byteToHex(c3));//C1 C2 C3拼装成加密字串return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(source) + Util.byteToHex(c3);}//数据解密public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException {if (privateKey == null || privateKey.length == 0) {return null;}if (encryptedData == null || encryptedData.length == 0) {return null;}//加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2String data = Util.byteToHex(encryptedData);/***分解加密字串* (C1 = C1标志位2位 + C1实体部分128位 = 130)* (C3 = C3实体部分64位  = 64)* (C2 = encryptedData.length * 2 - C1长度  - C2长度)*/byte[] c1Bytes = Util.hexToByte(data.substring(0, 130));int c2Len = encryptedData.length - 97;byte[] c2 = Util.hexToByte(data.substring(130, 130 + 2 * c2Len));byte[] c3 = Util.hexToByte(data.substring(130 + 2 * c2Len, 194 + 2 * c2Len));SM2 sm2 = SM2.Instance();BigInteger userD = new BigInteger(1, privateKey);//通过C1实体字节来生成ECPointECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);Cipher cipher = new Cipher();cipher.Init_dec(userD, c1);cipher.Decrypt(c2);cipher.Dofinal(c3);//返回解密结果return c2;}@SuppressWarnings("deprecation")public static void main(String[] args) throws Exception {BigInteger random = new BigInteger("83A2C9C8B96E5AF70BD480B472409A9A327257F1EBB73F5B073354B248668563", 16);SM2 sm2 = SM2.Instance();ECPoint ecPoint = sm2.ecc_point_g.multiply(random);System.out.println("坐标x1:" + ecPoint.getX().toBigInteger().toString(16));System.out.println("坐标y1:" + ecPoint.getY().toBigInteger().toString(16));//生成密钥对generateKeyPair();String plainText = "jdbc:mysql://10.22.68.1:3306/remote_issue_db_v2?useUnicode=true&amp;useSSL=false&amp;characterEncoding=UTF-8&amp;allowMultiQueries=true";byte[] sourceData = plainText.getBytes();System.out.println(BaseUtil.bytesToHexString(sourceData));//下面的秘钥可以使用generateKeyPair()生成的秘钥内容// 国密规范正式私钥String prik = "私钥";// 国密规范正式公钥String pubk = "公钥";System.out.println("加密: ");String cipherText = SM2Utils.encrypt(Util.hexToByte(pubk), sourceData);System.out.println(cipherText);System.out.println("解密: ");plainText = new String(SM2Utils.decrypt(Util.hexToByte(prik), Util.hexToByte(cipherText)));System.out.println(plainText);}
}

在sm2包下创建BaseUtil.java

import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;public class BaseUtil {/*** byte[]转十六进制字符串* string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串。** @param src 原数组* @return*/public static String bytesToHexString(byte[] src) {StringBuilder stringBuilder = new StringBuilder("");if (src == null || src.length <= 0) {return null;}for (int i = 0; i < src.length; i++) {int v = src[i] & 0xFF;String hv = Integer.toHexString(v);if (hv.length() < 2) {stringBuilder.append(0);}stringBuilder.append(hv);}return stringBuilder.toString();}public static String bytesToHexString(byte[] src, int endInx) {StringBuilder stringBuilder = new StringBuilder("");if (src == null || src.length <= 0) {return null;}for (int i = 0; i < endInx; i++) {int v = src[i] & 0xFF;String hv = Integer.toHexString(v);if (hv.length() < 2) {stringBuilder.append(0);}stringBuilder.append(hv);}return stringBuilder.toString();}/*** 十六进制转十进制整形** @param hexString* @return*/public static long hexToTen(String hexString) {return new BigInteger(hexString, 16).longValue();}/*** int转十六进制的字符串** @param value 整形* @param len   返回字符串的长度* @return*/public static String intToHexString(long value, int len) {String str = "00000000000000000000000000000000";// 32位String hexString = Long.toHexString(value);if (hexString.length() >= len) {hexString = hexString.substring(0, len);} else {hexString = str.substring(0, len - hexString.length()) + hexString;}return hexString;}/*** 十六进制字符串转byte[]** @param hexString 十六进制数* @return*/public static byte[] hexStringToBytes(String hexString) {if (hexString == null || hexString.equals("")) {return null;}if (hexString.length() % 2 == 1) {hexString = "0" + hexString;}hexString = hexString.toLowerCase();int length = (hexString.length() + 1) / 2;char[] hexChars = hexString.toCharArray();byte[] d = new byte[length];for (int i = 0; i < length; i++) {int pos = i * 2;d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));}return d;}/*** char转byep** @param c 字符* @return*/private static byte charToByte(char c) {return (byte) "0123456789abcdef".indexOf(c);}public static String longToString(int length, long data) {String dataStr = Long.toString(data);StringBuilder zero = new StringBuilder();int dataLen = dataStr.length();for (int i = 0; i < length - dataLen; i++) {zero.append("0");}zero.append(dataStr);return zero.toString();}public static int byteArrayToInt(byte[] res, int offset, boolean netByteSequence) {if (netByteSequence) {// 网络字节顺序(高位在前)int targets = (res[offset + 3] & 0xff) | ((res[offset + 2] << 8) & 0xff00) | ((res[offset + 1] << 24) >>> 8)| (res[offset] << 24);return targets;} else {// 非网络字节顺序(低位在前)int targets = (res[offset] & 0xff) | ((res[offset + 1] << 8) & 0xff00) | ((res[offset + 2] << 24) >>> 8)| (res[offset + 3] << 24);return targets;}}public static String doubleToString(double src, int dotLen) {String s = String.valueOf(src);int inx = s.lastIndexOf(".");String zeros = "00000000000000000000";if (inx == -1) {return s + "." + zeros.substring(0, dotLen);} else if (s.length() - 1 - inx >= dotLen) {return s.substring(0, inx + dotLen + 1);} else {return s + zeros.substring(0, dotLen - (s.length() - 1 - inx));}}/*** 字符串转int** @param s        字符串* @param defValue 缺省值* @return 转换结果*/public static int strToInt(String s, int defValue) {s = s.trim();if (s.length() == 0)return defValue;try {return Integer.parseInt(s);} catch (Exception e) {return defValue;}}public static boolean isMoney(String moneyString) {boolean result = false;if (moneyString.equals("")) {return false;}double temp = 0;try {temp = Double.valueOf(moneyString);result = true;} catch (Exception e) {// TODO: handle exceptionresult = false;}if (result) {moneyString = String.valueOf(temp);if (moneyString.indexOf(".") != -1 && moneyString.length() - 1 - moneyString.indexOf(".") > 2) {result = false;}}return result;}public static String fenToYuanStr(String src) {StringBuffer temp = new StringBuffer("");if (src.length() <= 2) {temp.append(Double.valueOf(src) / 100.0);} else {temp.append(src.substring(0, src.length() - 2));temp.append(".");temp.append(src.substring(src.length() - 2, src.length()));}return temp.toString();}/*** 转为unix时间** @param hexStr 16进制的字符串* @return*/public static Date String2UnixDate(String hexStr) {long timePoke = hexToTen(hexStr) * 1000l;Date date = new Date(timePoke);return date;}/*** 将i转换为两位数:例如 1转为01,11转为11** @param i* @return*/public static String numberTo01Format(int i) {return String.format("%02d", i);}/*** 二进制转为十进制** @param binary* @return*/public static int toTenFromBinaryString(String binary) {return Integer.parseInt(Integer.valueOf(binary, 2).toString());}/*** 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串** @param params 需要排序并参与字符拼接的参数组* @return 拼接后字符串*/public static String createLinkString(Map<String, Object> params) {List<String> keys = new ArrayList<String>(params.keySet());Collections.sort(keys);StringBuffer preStr = new StringBuffer("");for (int i = 0; i < keys.size(); i++) {String key = keys.get(i);if (params.get(key) != null) {String value = params.get(key).toString();preStr.append(key).append("=").append(value).append("&");}}return preStr.toString().substring(0, preStr.length() - 1);}/*** 字节数组异或运算** @param byteOne* @param byteTwo* @return*/public static byte[] xor(byte[] byteOne, byte[] byteTwo) {byte[] tempByte = new byte[byteOne.length];for (int flag = 0; flag < tempByte.length; flag++) {tempByte[flag] = (byte) (byteOne[flag] ^ byteTwo[flag]);}return tempByte;}/*** 字节数组链接** @param totalLen* @param bytes* @return*/public static byte[] arrayApend(int totalLen, byte[]... bytes) {byte[] tempByte = new byte[totalLen];int destPos = 0;for (int length = 0; length < bytes.length; length++) {System.arraycopy(bytes[length], 0, tempByte, destPos, bytes[length].length);destPos += bytes[length].length;}return tempByte;}/*** @return*/public static String paddingLen(String lenHex) {while (lenHex.length() < 4) {lenHex = "0" + lenHex;}return lenHex;}public static String paddingMacData(String data) {data = data + "80";while (data.length() % 32 != 0) {data = data + "00";}return data;}public static byte[] paddingEncryptData(String data) {if (data.length() % 32 != 0) {data = data + "80";}while (data.length() % 32 != 0) {data = data + "00";}return BaseUtil.hexStringToBytes(data);}public static byte[] paddingDecryptData(String data) {byte[] bytes = BaseUtil.hexStringToBytes(data);for (int i = 1; i < bytes.length; i++) {if (bytes[i - 1] == 125 && bytes[i] == -128) {return Arrays.copyOfRange(bytes, 0, i);}}return bytes;}/*** 填充数据** @param data* @param len* @return*/public static String padding(String data, int len) {while (data.length() < len) {data = "0" + data;}return data;}public static String paddingSslEncryptData(String data) {Integer paddingLen = (32 - data.length() % 32) / 2;if (paddingLen == 0) {paddingLen = 16;}Integer paddingValue = paddingLen - 1;String padding = "0" + Integer.toHexString(paddingValue);for (int index = 1; index <= paddingLen; index++) {data = data + padding;}return data;}public static byte[] paddingSslDecryptData(byte[] data) {byte[] padding = Arrays.copyOfRange(data, data.length - 1, data.length);Integer paddingLen = Integer.parseInt(BaseUtil.bytesToHexString(padding), 16) + 1;return Arrays.copyOfRange(data, 0, data.length - paddingLen);}
}

在sm2包下创建util.java


import java.math.BigInteger;public class Util {/*** 整形转换成网络传输的字节流(字节数组)型数据** @param num 一个整型数据* @return 4个字节的自己数组*/public static byte[] intToBytes(int num) {byte[] bytes = new byte[4];bytes[0] = (byte) (0xff & (num >> 0));bytes[1] = (byte) (0xff & (num >> 8));bytes[2] = (byte) (0xff & (num >> 16));bytes[3] = (byte) (0xff & (num >> 24));return bytes;}/*** 四个字节的字节数据转换成一个整形数据** @param bytes 4个字节的字节数组* @return 一个整型数据*/public static int byteToInt(byte[] bytes) {int num = 0;int temp;temp = (0x000000ff & (bytes[0])) << 0;num = num | temp;temp = (0x000000ff & (bytes[1])) << 8;num = num | temp;temp = (0x000000ff & (bytes[2])) << 16;num = num | temp;temp = (0x000000ff & (bytes[3])) << 24;num = num | temp;return num;}/*** 长整形转换成网络传输的字节流(字节数组)型数据** @param num 一个长整型数据* @return 4个字节的自己数组*/public static byte[] longToBytes(long num) {byte[] bytes = new byte[8];for (int i = 0; i < 8; i++) {bytes[i] = (byte) (0xff & (num >> (i * 8)));}return bytes;}/*** 大数字转换字节流(字节数组)型数据** @param n* @return*/public static byte[] byteConvert32Bytes(BigInteger n) {byte tmpd[] = (byte[]) null;if (n == null) {return null;}if (n.toByteArray().length == 33) {tmpd = new byte[32];System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);} else if (n.toByteArray().length == 32) {tmpd = n.toByteArray();} else {tmpd = new byte[32];for (int i = 0; i < 32 - n.toByteArray().length; i++) {tmpd[i] = 0;}System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);}return tmpd;}/*** 换字节流(字节数组)型数据转大数字** @param b* @return*/public static BigInteger byteConvertInteger(byte[] b) {if (b[0] < 0) {byte[] temp = new byte[b.length + 1];temp[0] = 0;System.arraycopy(b, 0, temp, 1, b.length);return new BigInteger(temp);}return new BigInteger(b);}/*** 根据字节数组获得值(十六进制数字)** @param bytes* @return*/public static String getHexString(byte[] bytes) {return getHexString(bytes, true);}/*** 根据字节数组获得值(十六进制数字)** @param bytes* @param upperCase* @return*/public static String getHexString(byte[] bytes, boolean upperCase) {String ret = "";for (int i = 0; i < bytes.length; i++) {ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);}return upperCase ? ret.toUpperCase() : ret;}/*** 打印十六进制字符串** @param bytes*/public static void printHexString(byte[] bytes) {for (int i = 0; i < bytes.length; i++) {String hex = Integer.toHexString(bytes[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}System.out.print("0x" + hex.toUpperCase() + ",");}System.out.println("");}/*** Convert hex string to byte[]** @param hexString the hex string* @return byte[]*/public static byte[] hexStringToBytes(String hexString) {if (hexString == null || hexString.equals("")) {return null;}hexString = hexString.toUpperCase();int length = hexString.length() / 2;char[] hexChars = hexString.toCharArray();byte[] d = new byte[length];for (int i = 0; i < length; i++) {int pos = i * 2;d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));}return d;}/*** Convert char to byte** @param c char* @return byte*/public static byte charToByte(char c) {return (byte) "0123456789ABCDEF".indexOf(c);}/*** 用于建立十六进制字符的输出的小写字符数组*/private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};/*** 用于建立十六进制字符的输出的大写字符数组*/private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};/*** 将字节数组转换为十六进制字符数组** @param data byte[]* @return 十六进制char[]*/public static char[] encodeHex(byte[] data) {return encodeHex(data, true);}/*** 将字节数组转换为十六进制字符数组** @param data        byte[]* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式* @return 十六进制char[]*/public static char[] encodeHex(byte[] data, boolean toLowerCase) {return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);}/*** 将字节数组转换为十六进制字符数组** @param data     byte[]* @param toDigits 用于控制输出的char[]* @return 十六进制char[]*/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;}/*** 将字节数组转换为十六进制字符串** @param data byte[]* @return 十六进制String*/public static String encodeHexString(byte[] data) {return encodeHexString(data, true);}/*** 将字节数组转换为十六进制字符串** @param data        byte[]* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式* @return 十六进制String*/public static String encodeHexString(byte[] data, boolean toLowerCase) {return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);}/*** 将字节数组转换为十六进制字符串** @param data     byte[]* @param toDigits 用于控制输出的char[]* @return 十六进制String*/protected static String encodeHexString(byte[] data, char[] toDigits) {return new String(encodeHex(data, toDigits));}/*** 将十六进制字符数组转换为字节数组** @param data 十六进制char[]* @return byte[]* @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常*/public static byte[] decodeHex(char[] data) {int len = data.length;if ((len & 0x01) != 0) {throw new RuntimeException("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;}/*** 将十六进制字符转换成一个整数** @param ch    十六进制char* @param index 十六进制字符在字符数组中的位置* @return 一个整数* @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常*/protected static int toDigit(char ch, int index) {int digit = Character.digit(ch, 16);if (digit == -1) {throw new RuntimeException("Illegal hexadecimal character " + ch+ " at index " + index);}return digit;}/*** 数字字符串转ASCII码字符串** @param content 字符串* @return ASCII字符串*/public static String StringToAsciiString(String content) {String result = "";int max = content.length();for (int i = 0; i < max; i++) {char c = content.charAt(i);String b = Integer.toHexString(c);result = result + b;}return result;}/*** 十六进制转字符串** @param hexString  十六进制字符串* @param encodeType 编码类型4:Unicode,2:普通编码* @return 字符串*/public static String hexStringToString(String hexString, int encodeType) {String result = "";int max = hexString.length() / encodeType;for (int i = 0; i < max; i++) {char c = (char) hexStringToAlgorism(hexString.substring(i * encodeType, (i + 1) * encodeType));result += c;}return result;}/*** 十六进制字符串装十进制** @param hex 十六进制字符串* @return 十进制数值*/public static int hexStringToAlgorism(String hex) {hex = hex.toUpperCase();int max = hex.length();int result = 0;for (int i = max; i > 0; i--) {char c = hex.charAt(i - 1);int algorism = 0;if (c >= '0' && c <= '9') {algorism = c - '0';} else {algorism = c - 55;}result += Math.pow(16, max - i) * algorism;}return result;}/*** 十六转二进制** @param hex 十六进制字符串* @return 二进制字符串*/public static String hexStringToBinary(String hex) {hex = hex.toUpperCase();String result = "";int max = hex.length();for (int i = 0; i < max; i++) {char c = hex.charAt(i);switch (c) {case '0':result += "0000";break;case '1':result += "0001";break;case '2':result += "0010";break;case '3':result += "0011";break;case '4':result += "0100";break;case '5':result += "0101";break;case '6':result += "0110";break;case '7':result += "0111";break;case '8':result += "1000";break;case '9':result += "1001";break;case 'A':result += "1010";break;case 'B':result += "1011";break;case 'C':result += "1100";break;case 'D':result += "1101";break;case 'E':result += "1110";break;case 'F':result += "1111";break;}}return result;}/*** ASCII码字符串转数字字符串** @param content ASCII字符串* @return 字符串*/public static String AsciiStringToString(String content) {String result = "";int length = content.length() / 2;for (int i = 0; i < length; i++) {String c = content.substring(i * 2, i * 2 + 2);int a = hexStringToAlgorism(c);char b = (char) a;String d = String.valueOf(b);result += d;}return result;}/*** 将十进制转换为指定长度的十六进制字符串** @param algorism  int 十进制数字* @param maxLength int 转换后的十六进制字符串长度* @return String 转换后的十六进制字符串*/public static String algorismToHexString(int algorism, int maxLength) {String result = "";result = Integer.toHexString(algorism);if (result.length() % 2 == 1) {result = "0" + result;}return patchHexString(result.toUpperCase(), maxLength);}/*** 字节数组转为普通字符串(ASCII对应的字符)** @param bytearray byte[]* @return String*/public static String byteToString(byte[] bytearray) {String result = "";char temp;int length = bytearray.length;for (int i = 0; i < length; i++) {temp = (char) bytearray[i];result += temp;}return result;}/*** 二进制字符串转十进制** @param binary 二进制字符串* @return 十进制数值*/public static int binaryToAlgorism(String binary) {int max = binary.length();int result = 0;for (int i = max; i > 0; i--) {char c = binary.charAt(i - 1);int algorism = c - '0';result += Math.pow(2, max - i) * algorism;}return result;}/*** 十进制转换为十六进制字符串** @param algorism int 十进制的数字* @return String 对应的十六进制字符串*/public static String algorismToHEXString(int algorism) {String result = "";result = Integer.toHexString(algorism);if (result.length() % 2 == 1) {result = "0" + result;}result = result.toUpperCase();return result;}/*** HEX字符串前补0,主要用于长度位数不足。** @param str       String 需要补充长度的十六进制字符串* @param maxLength int 补充后十六进制字符串的长度* @return 补充结果*/static public String patchHexString(String str, int maxLength) {String temp = "";for (int i = 0; i < maxLength - str.length(); i++) {temp = "0" + temp;}str = (temp + str).substring(0, maxLength);return str;}/*** 将一个字符串转换为int** @param s          String 要转换的字符串* @param defaultInt int 如果出现异常,默认返回的数字* @param radix      int 要转换的字符串是什么进制的,如16 8 10.* @return int 转换后的数字*/public static int parseToInt(String s, int defaultInt, int radix) {int i = 0;try {i = Integer.parseInt(s, radix);} catch (NumberFormatException ex) {i = defaultInt;}return i;}/*** 将一个十进制形式的数字字符串转换为int** @param s          String 要转换的字符串* @param defaultInt int 如果出现异常,默认返回的数字* @return int 转换后的数字*/public static int parseToInt(String s, int defaultInt) {int i = 0;try {i = Integer.parseInt(s);} catch (NumberFormatException ex) {i = defaultInt;}return i;}/*** 十六进制串转化为byte数组** @return the array of byte*/public static byte[] hexToByte(String hex)throws IllegalArgumentException {if (hex.length() % 2 != 0) {throw new IllegalArgumentException();}char[] arr = hex.toCharArray();byte[] b = new byte[hex.length() / 2];for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {String swap = "" + arr[i++] + arr[i];int byteint = Integer.parseInt(swap, 16) & 0xFF;b[j] = new Integer(byteint).byteValue();}return b;}/*** 字节数组转换为十六进制字符串** @param b byte[] 需要转换的字节数组* @return String 十六进制字符串*/public static String byteToHex(byte b[]) {if (b == null) {throw new IllegalArgumentException("Argument b ( byte array ) is null! ");}String hs = "";String stmp = "";for (int n = 0; n < b.length; n++) {stmp = Integer.toHexString(b[n] & 0xff);if (stmp.length() == 1) {hs = hs + "0" + stmp;} else {hs = hs + stmp;}}return hs.toUpperCase();}public static byte[] subByte(byte[] input, int startIndex, int length) {byte[] bt = new byte[length];for (int i = 0; i < length; i++) {bt[i] = input[i + startIndex];}return bt;}
}

sm2国密算法准备完毕

重写HikariDataSource

未指出的依赖请自行百度填充

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;import com.xsluck.exception.ApplicationException;
import com.xsluck.sm2.SM2Utils;
import com.xsluck.sm2.Util;
import com.zaxxer.hikari.HikariDataSource;/*** 重写 HikariDataSource 实现密码加密* * @author xsluck**/
public class DataSourceConfig extends HikariDataSource {private String password;private String username;private String jdbcUrl;/*** 此默认公钥对应此默认私钥*/
//  private String pubk = "0431B2FB78722989C601339FF7D751CAA30AF304864DED63A2C2E87D54E9BCCD8679D29CDD760EE8146A7A0A26BF257BDA01C822411981E2EC635573D8DDE2D98A";/*** 默认私钥,请自动生成替换*/private String oldprik = "65E54A36668A6C8D5FB1C133529322A8B36A65CAE158B0003EB0ED45D812AC14";/*** 设置是否加密*/@Value("${datasource.encryption:#{false}}")private boolean encryption = false;@Overridepublic String getPassword() {if (StringUtils.isNotBlank(password))return password;String sm2Password = super.getPassword();if (!encryption)return sm2Password;if (null == sm2Password)return null;try {byte[] sm2Passwords = SM2Utils.decrypt(Util.hexToByte(oldprik), Util.hexToByte(sm2Password));password = new String(sm2Passwords, "UTF-8");return password;} catch (Exception e) {throw new ApplicationException("数据库密码解密失败!", e);}}@Overridepublic String getUsername() {if (StringUtils.isNotBlank(username))return username;String sm2username = super.getUsername();if (!encryption)return sm2username;if (null == sm2username)return null;try {byte[] sm2usernames = SM2Utils.decrypt(Util.hexToByte(oldprik), Util.hexToByte(sm2username));username = new String(sm2usernames, "UTF-8");return username;} catch (Exception e) {throw new ApplicationException("数据库用户名解密失败!", e);}}@Overridepublic String getJdbcUrl() {if (StringUtils.isNotBlank(jdbcUrl))return jdbcUrl;String sm2jdbcUrl = super.getJdbcUrl();if (!encryption)return sm2jdbcUrl;if (null == sm2jdbcUrl)return null;try {byte[] jdbcUrls = SM2Utils.decrypt(Util.hexToByte(oldprik), Util.hexToByte(sm2jdbcUrl));jdbcUrl = new String(jdbcUrls, "UTF-8");return jdbcUrl;} catch (Exception e) {throw new ApplicationException("数据库连接地址解密失败!", e);}}
}

注入bean

 @Bean(name = "dataSource")@Primary@ConfigurationProperties(ignoreUnknownFields = false,prefix="spring.datasource.hikari")public HikariDataSource hikariDataSource() {HikariDataSource dataSourceConfig = new DataSourceConfig();return dataSourceConfig;}

配置文件设置

##数据源配置
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.max-lifetime=60000
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.read-only=false
spring.datasource.hikari.validation-timeout=3000
spring.datasource.hikari.connection-test-query=select 1
##数据库连接配置
#配置是否对jdbc链接数据进行加密,未设置默认false,不加密
datasource.encryption=true
spring.datasource.hikari.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.hikari.jdbc-url=04EC59828574B2E8C1EA0FF235DC870143614C415A84F031DBF006E4A4A4687883C2BEB212AF67EBC7D21F005A4DB9A45A4063541E1330F54C2E66DA1B137159367509C4B0ED8070EFFC6B6555009740B3C1DE0F21D631601A6270EBE5BA6A8CD430E96C7446C50772927EC58124756E2E47DC052F24337DE00E08C517C0398F1B64555A56333BADEE11ECD06B46039B7EDF4ECCB819363E0C92F7C676080F05B51E20C8BE8BAD27C7B7124D1E91643C15BE94E5539D51AB69BD3A20E03A66DC831415FF414D46CD5CC00B333F4AE0891D5144FF533FBB0FA1D9D377E23D5BDDB97BD03FF040E906
spring.datasource.hikari.username=04980BC2FEC31AF874D240B63BB2E497C75A5D09694BB6E92B83959C95D89E96080AD23D5D181DB7470588DF5BA9CA7AA4E42A2428B43F2FB0AD9F27E2B347BCA2B86CEF3C698ED495F163086CF5496DCA07245047F72D314458A433697A072A6C6364B374
spring.datasource.hikari.password=04980BC2FEC31AF874D240B63BB2E497C75A5D09694BB6E92B83959C95D89E96080AD23D5D181DB7470588DF5BA9CA7AA4E42A2428B43F2FB0AD9F27E2B347BCA2B86CEF3C698ED495F163086CF5496DCA07245047F72D314458A433697A072A6C6364B374

初始加密

 private final String pubk = "04A00567ED663623FA631A249DA7B4F1DDD18EE0AB2231980FAF112CA7A48B3962A91BE64A77B9236EA0FF10A67D35EF8F171DE7008E7519B0B086894FBC10D9DD";private final String prik = "56693CC5A3D86059976B0FFBB1A0CDAB78000B895FEB33CC2AE4A0497E9BFB5A";/*** 数据库连接SM2加密 公钥请勿私自替换,否则会造成解密失败 如替换私钥,要重新生成SM2公私钥对* * @throws Exception*/@Testvoid test() throws Exception {generateKeyPair();encryption("jdbc:mysql:///test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false");}/*** 加密* @param 待加密数据* @throws Exception*/void encryption(String plainText) throws Exception {byte[] sourceData = plainText.getBytes();String cipherText = SM2Utils.encrypt(Util.hexToByte(pubk), sourceData);System.out.println("明文数据:" + plainText);System.out.println("转换结果:" + BaseUtil.bytesToHexString(sourceData));System.out.println("加密结果: " + cipherText);String Text = new String(SM2Utils.decrypt(Util.hexToByte(prik), Util.hexToByte(cipherText)));System.out.println("解密结果:"+Text);}/*** 生成公私密钥*/void generateKeyPair() {SM2Utils.generateKeyPair();}

test

公钥: 043C0A658FBC85BB0AF3D8EC79009569073D1DC7A2AAD029E6062A8F2B8890D075CCD4DBA2FD9DEA3F6708358D520C619233B63B3BFB01E9BAC6864C882DA082C3
私钥: 294EAC75BA636A7A03ACBDF1F14E89953C3404912DF34416AA43855DB62C729E
明文数据:jdbc:mysql:///test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
转换结果:6a6462633a6d7973716c3a2f2f2f746573743f757365556e69636f64653d7472756526636861726163746572456e636f64696e673d5554462d3826616c6c6f774d756c7469517565726965733d747275652675736553534c3d66616c7365
加密结果: 04738CA3D1FF864B06657D940E3BA96A7C341A574103DCE7B1945B2D24808FC7C4CDCD2BA859C399D2C4B6D463E480D14BF929C234CE9CFB151C9E200353A4530E3432C60851B33B21023F8882D4A7BFD92815106B56FC06D63C17EFE3B63AB497E857AAB686E25C24C489AF7310393D183B3A9F9EEF11260DBBAD2C27C71C9A43FF71583D8FC9575266A903653CD59922EF1EFE0D017766DB5BE9B8442242C8B3D4B38F0A533C2FF8FC6F5CF22D1C0F76FE3ADE3C7D9126993861DC519383
解密结果:jdbc:mysql:///test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false

注意:

要保存好私钥,公钥用于加密,私钥用于解密

注意判断jdbc连接里的&是否是直接使用&还是使用它的转义符

配置文件加密 HikariDataSource相关推荐

  1. php 配置文件加密工具类,SpringBoot集成Jasypt安全框架以及配置文件内容加密(代码示例)...

    本篇文章给大家带来的内容是关于SpringBoot集成Jasypt安全框架以及配置文件内容加密(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 我们在SpringBoot项 ...

  2. ASP.NET 配置文件加密

    众所周知,web.config可以存储包括数据库链接在内的众多信息,所以为配置文件加密有时候就显得必要了. 1.加密前的配置文件如下: Web.config 1 <?xml version=&q ...

  3. NET2.0配置文件加密(WEBWindows)

    posted on 2006年5月6日 15:42 由 吴頔 WEB篇    网上已经有很多文章提到:     ASP.NET 2.0加密Web.config 配置文件      Keeping se ...

  4. java 配置文件加密_Spring cloud config 配置文件加密方式

    前言 我们会使用git来保存我们项目的配置文件,但是文件中总有一些敏感数据,对于这些敏感数据我们通常需要给它加密,加密通常有两种加密方式,一种是对称加密,一种是非对称加密,对称加密简单方便,但是安全性 ...

  5. SpringBoot 配置文件加密的两种方式

    SpringBoot配置文件加密的两种方式 jasypt使用方式 用法一: 1.Application.java上增加注解@EnableEncryptableProperties(jasypt-spr ...

  6. 配置文件加密(Jasypt的简单使用)

    title: 配置文件加密(Jasypt的简单使用) categories: Jasypt tags: Jasypt 需求引入 当我们需要对SpringBoot项目的配置文件中的信息进行加密时,如数据 ...

  7. Springboot之Jasypt配置文件加密/解密

    Jasypt配置文件加密/机密 一.Jasypt介绍 二.Springboot整合Jasypt 2.1 环境配置 2.2 添加依赖 2.3 添加Jasypt配置 2.4 编写加/解密工具类 2.5 修 ...

  8. 使用Jasypt对SpringBoot配置文件加密(数据源为SpringBoot默认的数据源HikariDataSource)

    目录 一.引入jar包依赖(pom.xml) 二.可以写个main函数,写一个用于生成用户名和密码的类,如下: 三.在配置文件(.yml或者.properties文件中) 四.启动时候常出现的问题以及 ...

  9. spring boot 配置文件加密数据库用户名/密码

    这篇文章为大家分享spring boot的配置文件properties文件里面使用经过加密的数据库用户名+密码,因为在自己做过的项目中,有这样的需求,尤其是一些大公司,或者说上市公司,是不会把这些敏感 ...

最新文章

  1. 在阿里当PM都需要做什么?
  2. 创建型设计模式对比总结 设计模式(八)
  3. linux memcached 的安装
  4. 发现你的身形——OpenCV图像轮廓
  5. 同步/异步与阻塞/非阻塞的区别
  6. 小结三种控制路由发布的方法
  7. C++:类占用的字节内存
  8. jQuery常用技巧大放送
  9. Centos 7 定时关机
  10. Basic INFO: InstallShield 2012安装过程
  11. [elixir! #0024] 引擎盖下, `Channel.push` 如何运作
  12. 计算机设备安全隐患排查,安全安全隐患排查实施方案
  13. c语言转化音乐格式转换器安卓版,音频提取格式转换
  14. HTML开心人人新浪微薄等
  15. 计算机没有检查到您的u盾,Win10检测不到U盾怎么办?
  16. QT实现绘制箱须图(盒须图)
  17. 启动Jenkins时报错,localhost拒绝了我们的连接请求
  18. 六大主流安卓模拟器(腾讯、逍遥、mumu、夜神、雷电、蓝叠)的测评:游戏以外的使用
  19. admi后台 vue_Vue+ElementUI的后台管理框架
  20. 人脸识别接口_DS-K5603-Z 海康威视人员通道人脸识别组件 1万人脸库 10.1英寸LCD触摸显示屏_DS-K5603-Z_DS-K5603-Z...

热门文章

  1. NRF52832-QFAA、NRF52840-QIAA性能区别-蓝牙智能手环穿戴
  2. 【Flink实战系列】Lorg/apache/flink/kafka/shaded/org/apache/kafka/clients/consumer/ConsumerRecord;)Ljava/
  3. python 英语翻译 excel_Python调用百度翻译api批量翻译Excel这工作效率
  4. libusb-win32介绍
  5. Postgresql-11 根据多字段创建分区表
  6. python爬虫模拟点击和输入_爬虫笔记关于鼠标点击和内容输入
  7. (五)Kotlin简单易学 基础语法-初始函数(下)
  8. c51语言转换ASCII码,数据转换:C51数字转字符最快速的方法 ASCII转换
  9. html+css的音乐网站
  10. 淘宝、拼多多、京东等购物平台的优惠券公众号免费搭建持续更新