- KDFDecryptedDataSourceFactory.java 파일 생성하여 소스내 적당한 util 폴더안에 넣어준다.

package mydomain.util.encrypt;  // 패키지명 수정

import java.security.MessageDigest;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.dbcp.BasicDataSourceFactory;

public class KDFDecryptedDataSourceFactory extends BasicDataSourceFactory {
	private final String key = "dfkjlajf902jklf";  // 암호화 키 설정
	private final String symmAlg = "AES";

	public static String randomIv(int len) {
		StringBuffer strBuffer = new StringBuffer();
		String iv = null, ivS = null;
		Random rd = new Random();
		for (int i = 0; i < len; i++) {
			if (iv == null || iv.length() < len) {
				ivS = Integer.toHexString(rd.nextInt());
				iv = strBuffer.append(ivS).toString();
			}
			if (iv.length() > len) {
				iv = iv.substring(0, len);
				break;
			}
			if (iv.length() == len)
				break;
		}
		return iv;
	}

	public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
		if (obj instanceof Reference) {
			setUsername((Reference) obj);
			setPassword((Reference) obj);
			setUrl((Reference) obj);
		}
		return super.getObjectInstance(obj, name, nameCtx, environment);
	}

	private void setUrl(Reference ref) throws Exception {
		findDecryptAndReplace("url", ref);
	}

	private void setUsername(Reference ref) throws Exception {
		findDecryptAndReplace("username", ref);
	}

	private void setPassword(Reference ref) throws Exception {
		findDecryptAndReplace("password", ref);
	}

	private void findDecryptAndReplace(String refType, Reference ref) throws Exception {
		int idx = find(refType, ref);
		String decrypted = decrypt(ref.get(idx).getContent().toString());
		replace(idx, refType, decrypted, ref);
	}

	private void replace(int idx, String refType, String newValue, Reference ref) throws Exception {
		ref.remove(idx);
		ref.add(idx, new StringRefAddr(refType, newValue));
	}

	private int find(String addrType, Reference ref) throws Exception {
		Enumeration enu = ref.getAll();
		for (int i = 0; enu.hasMoreElements(); i++) {
			RefAddr addr = (RefAddr) enu.nextElement();
			if (addr.getType().compareTo(addrType) == 0)
				return i;
		}
		throw new Exception("The \"" + addrType + "\" name/value pair was not found"
				+ " in the Reference object. The reference Object is" + " " + ref.toString());
	}

	private String decrypt(String ciphertext) throws Exception {
		MessageDigest md = null;
		md = MessageDigest.getInstance("SHA-256");
		md.update(key.getBytes());
		byte[] hashVal = md.digest();
		byte[] key = new byte[16];
		System.arraycopy(hashVal, 0, key, 0, 16);
		byte[] iv = new byte[16];
		System.arraycopy(hashVal, 4, iv, 0, 16);
		String encAlg = (symmAlg + "/CBC/PKCS5Padding");
		Cipher cipher = Cipher.getInstance(encAlg);
		cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, symmAlg), new IvParameterSpec(iv));
		String decryptedVal = new String(cipher.doFinal(Hex.decodeHex(ciphertext.toCharArray())));
		return decryptedVal;
	}
}

 

 

- 암호화된 url, username, password 복호화를 해본다.

package test.encrypt;

import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;

public class KDFEncrypted {
	public static void main(String[] args) { 
		
		String key = "dfkjlajf902jklf";
		String url = "jdbc:mysql://127.0.0.1:3306/mydb?characterEncoding=UTF-8"; 
		String username = "root"; 
		String password= "root123";
		
		try {
			System.out.println("########### Encrypt ############"); 
			byte[] enc_url = encrypt("AES", key.getBytes(), url.getBytes()); 
			byte[] enc_username = encrypt("AES", key.getBytes(), username.getBytes()); 
			byte[] enc_password = encrypt("AES", key.getBytes(), password.getBytes()); 
			String hex_url = new String(Hex.encodeHex(enc_url)); 
			String hex_username = new String(Hex.encodeHex(enc_username)); 
			String hex_password = new String(Hex.encodeHex(enc_password)); 
			System.out.println("enc_hex_url : " + hex_url); 
			System.out.println("enc_hex_username : " + hex_username); 
			System.out.println("enc_hex_password : " + hex_password);
		} catch (Exception e){ 
			e.printStackTrace(); 
		} 
	}


	public static byte[] encrypt(String symmAlg, byte[] passwd, byte[] tbeData) throws Exception { 
		byte[] encData = null; 
		MessageDigest md = null;
		md = MessageDigest.getInstance("SHA-256"); 
		md.update(passwd); 
		byte[] hashVal = md.digest(); 
		byte[] key = new byte[16]; 
		System.arraycopy(hashVal, 0, key, 0, 16); 
		byte[] iv = new byte[16]; 
		System.arraycopy(hashVal, 4, iv, 0, 16); 
		String encAlg = (symmAlg + "/CBC/PKCS5Padding"); 
		Cipher cipher = Cipher.getInstance(encAlg); 
		cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, symmAlg), new IvParameterSpec(iv)); 
		encData = cipher.doFinal(tbeData); 
		return encData; 
	}
}

 

- DB url, username, password 값의 암호화된 String을 구한다. (테스트)

package sbbms.encrypt;

import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;

public class KDFDecryptedTest{
	private final static String key = "dfkjlajf902jklf";
	private final static String symmAlg = "AES";
	
	public static void main(String[] args) { 
		
		String key = "dfkjlajf902jklf";
		 
		String url = "54515aeac48aeac48aec481a38de7735e1f531eds5fes54515aeac48aeac48aec481a38de7735e1f531eds5fes"; 
		String username = "a7e80ba13e818a3177e7731c156011a19f"; 
		String password= "c8e0c3e8bba7731c156011a731c156e818";
		
		try { 
			
			System.out.println("url : " + decrypt(url));
			System.out.println("username : " + decrypt(username));
			System.out.println("password : " + decrypt(password));
		} catch (Exception e){ 
			e.printStackTrace(); 
		} 
	}
	
	static String decrypt(String ciphertext) throws Exception {
			MessageDigest md = null;
			md = MessageDigest.getInstance("SHA-256");
			md.update(key.getBytes());
			byte[] hashVal = md.digest();
			byte[] key = new byte[16];
			System.arraycopy(hashVal, 0, key, 0, 16);
			byte[] iv = new byte[16];
			System.arraycopy(hashVal, 4, iv, 0, 16);
			String encAlg = (symmAlg + "/CBC/PKCS5Padding");
			Cipher cipher = Cipher.getInstance(encAlg);
			cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, symmAlg), new IvParameterSpec(iv));
			String decryptedVal = new String(cipher.doFinal(Hex.decodeHex(ciphertext.toCharArray())));
			return decryptedVal;
		}

 
}

 

- server.xml에 factory, url, username, password 부분을 등록해 준다.

    <Resource name="jdbc/mydb"
              global="jdbc/mydb"
              auth="Container"
              type="javax.sql.DataSource"
              driverClassName="com.mysql.jdbc.Driver"
              factory="mydomain.util.KDFDecryptedDataSourceFactory"
              url="54515aeac48aeac48aec481a38de7735e1f531eds5fes"
              username="a7e80ba13e818a3177e7731c156011a19f"
              password="c8e0c3e8bba7731c156011a731c156e818"
              maxActive="20"
              maxIdle="20"
              minIdle="5"
              maxWait="3000"
              validationQuery="SELECT 1"
              validationInterval="30000"
              />

 

 

 

[출처]

https://ynzu-dev.tistory.com/entry/Tomcat-JNDI-%EC%A0%95%EB%B3%B4-%EC%95%94%ED%98%B8%ED%99%94DB%EC%A0%95%EB%B3%B4-url-username-passowrd-KDF-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%9D%B4%EC%9A%A9

 

 

+ Recent posts