반응형
1. url, username, password를 encrypt 한다.
- KDFEncrypted.java
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 = "test";
String url = "jdbc:tibero:thin:@10.10.10.XX:XXXX:tibero";
String username = "root";
String password= "1q2w3e4r";
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;
//try {
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;
}
}
=> KDF Encrypt 후 Hex Encoding, key값은 decrypt할 때 사용한다.(해당 예제에서 key는 test라는 string data)
2. Server.xml에 JNDI를 등록한다
<Context allowCasualMultipartParsing="true" docBase="project1"
path="/sample" reloadable="true" source="org.eclipse.jst.jee.server:project1">
<Resource auth="Container"
defaultAutoCommit="false"
driverClassName="com.tmax.tibero.jdbc.TbDriver"
factory="com.project1.framework.jndi.KDFDecryptedDataSourceFactory"
initialSize="1" maxActive="2"
maxWait="10000" minIdle="2"
name="jdbc/project1"
url="ac0973fa30774730995c2ff93353836ac102d1a795207b10ec353e6dbd01dd6e0d1ded3d41cbc9cce87c78b6b1ec6a8d"
username="5c5f0fc1f068b4c54698e71fc0982f1b"
password="f334da1d60b3e0e0d8d89802cf5209d3"
type="javax.sql.DataSource"
validationQuery="select 1 from dual" />
</Context>
=> 여기서 주의할 점은 factory, url, username, password이다.
KDFEncrypted.java로 부터 얻은 url, username, password를 세팅해주며, factory는 3번을 참고한다.
3. KDFDecryptedDataSourceFactory.java
package com.project1.framework.jndi;
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 = "test";
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;
}
}
728x90
반응형
'개발 > Web' 카테고리의 다른 글
[Spring Boot] spring security - CSRF 적용 , +) ajax csrf 적용 (0) | 2021.12.07 |
---|---|
[Spring Boot] mybatis 적용하기 (0) | 2021.12.06 |
[JSP/HTML] ERR_CACHE_MISS 에러 발생 (0) | 2021.12.01 |
[Apache] web-was 연동, socket_timeout 설정 이슈 (0) | 2021.11.30 |
[Spring] Scheduler(스프링 스케줄러) 설정하기 (0) | 2021.11.30 |
댓글