commit aa6b2cc3e8b30b44af996f5b258cd42456ad34a6 Author: mjkhan21 Date: Fri Jan 19 13:21:29 2024 +0900 최초 커밋 diff --git a/3rd-party/dguard/conf/dguard.conf b/3rd-party/dguard/conf/dguard.conf new file mode 100644 index 0000000..141cbc0 --- /dev/null +++ b/3rd-party/dguard/conf/dguard.conf @@ -0,0 +1,41 @@ +# DGuard Java API Agent Configuration File +isEncrypt=false +daemon_number=5 +daemon_ip=211.119.124.9 +daemon_ip2=127.0.0.1 +daemon_ip3=127.0.0.1 +daemon_port=9999 +log_level=5 +cache=ON +info_index=1 +certification=null +private_key=null +Query_Collection_Mode=3 +db_type=oracle +token_file=3rd-party/dguard/token/xit_agent.token +audit_path=3rd-party/dguard/logs/ +server_name=localhost +audit_option=false +prove_mode=false +DBuser=oracle +SecureId= +SecurePwd= +TokenPwd= +Double_Enc_Flag=true +Double_Enc_Error_Flag=false +Random_Algorithm=SHA256DRBG +log_server_use=false +log_server_ip=127.0.0.1 +log_server_port=19999 +acc_flag=false +Timeout=3000 +Policy_File_Flag=false +Policy_File_Path= +Trim_Flag=true +Exception_Flag=true +Encoding_Flag=false +Encoding_Type=UTF-8 +BLOB_Decrypt_Size=976 +Hmac_Digest_Use=false +Jar_HMAC_Checksum=cAKi10ktdv9T+G1BY+ax0eIHD4Y0WM8KFHB6BVupcx8= +Config_HMAC_Checksum=nkNp7yruN6EJ5XLYkSdDZVrATe99sK7qBsz9Yw+2MBY= diff --git a/3rd-party/dguard/lib/MagicJCrypto-v2.0.0.0.jar.hmac b/3rd-party/dguard/lib/MagicJCrypto-v2.0.0.0.jar.hmac new file mode 100644 index 0000000..decc5f3 --- /dev/null +++ b/3rd-party/dguard/lib/MagicJCrypto-v2.0.0.0.jar.hmac @@ -0,0 +1 @@ +7141df12354b9cc23474c858645b9859c349215e4c40bdc477840ae58164a751 diff --git a/3rd-party/dguard/sample/APITest2.class b/3rd-party/dguard/sample/APITest2.class new file mode 100644 index 0000000..d4fcef3 Binary files /dev/null and b/3rd-party/dguard/sample/APITest2.class differ diff --git a/3rd-party/dguard/sample/APITest2.java b/3rd-party/dguard/sample/APITest2.java new file mode 100644 index 0000000..107bdda --- /dev/null +++ b/3rd-party/dguard/sample/APITest2.java @@ -0,0 +1,36 @@ +import com.Ineb.Dguard.*; +import com.Ineb.Exception.DguardLoginException; +import com.Ineb.Exception.DguardNetworkException; +import com.Ineb.Exception.DGuardPropertyException; + +import java.sql.*; +import java.util.*; +import java.io.*; + +public class APITest2 { + + public static void main(String[] args) { + try { + DguardManager dm = DguardManager.Init("db_agent", "Agent!1700", "Agent!1700", "./3rd-party/dguard/conf/dguard.conf"); + + String Table = "CRYPTO"; + String Column1 = "PWD"; + String Column2 = "ENC"; + String[] Data = {"1234", "000010000001", "9999999999999"}; + + String HashStr = dm.MsgDigest(Table, Column1, Data[0]); + System.out.println("MsgDigest " + " : [" + HashStr + "]"); + + String EncStr; + String DecStr; + for (int i = 0; i < Data.length; i++) { + EncStr = dm.Encrypt(Table, Column2, Data[i]); + System.out.println("Encrypt " + i + " : [" + EncStr + "]"); + DecStr = dm.Decrypt(Table, Column2, EncStr); + System.out.println("Decrypt " + i + " : [" + DecStr + "]"); + } + } catch(Exception e) { + e.printStackTrace(); + } + } +} diff --git a/3rd-party/dguard/sample/compile.bat b/3rd-party/dguard/sample/compile.bat new file mode 100644 index 0000000..16753b7 --- /dev/null +++ b/3rd-party/dguard/sample/compile.bat @@ -0,0 +1,2 @@ +javac -classpath C:\Ineb\lib\SecureDriver.jar;C:\Ineb\lib\INICrypto_v4.0.4.jar;C:\Ineb\lib\INISAFEPKI_v1.1.0.jar;C:\Ineb\lib\tibero4-jdbc.jar APITest2.java + diff --git a/3rd-party/dguard/sample/compile.sh b/3rd-party/dguard/sample/compile.sh new file mode 100644 index 0000000..d00daf7 --- /dev/null +++ b/3rd-party/dguard/sample/compile.sh @@ -0,0 +1,2 @@ +javac -classpath ../lib/DguardAPI.jar:../lib/MagicJCrypto-v2.0.0.0.jar:../lib/log4j-1.2.17.jar APITest2.java + diff --git a/3rd-party/dguard/sample/mysql/MySQLDec.class b/3rd-party/dguard/sample/mysql/MySQLDec.class new file mode 100644 index 0000000..48509d4 Binary files /dev/null and b/3rd-party/dguard/sample/mysql/MySQLDec.class differ diff --git a/3rd-party/dguard/sample/mysql/MySQLDec.java b/3rd-party/dguard/sample/mysql/MySQLDec.java new file mode 100644 index 0000000..1650d47 --- /dev/null +++ b/3rd-party/dguard/sample/mysql/MySQLDec.java @@ -0,0 +1,69 @@ +import com.Ineb.Dguard.*; +import com.Ineb.Exception.DguardLoginException; +import com.Ineb.Exception.DguardNetworkException; +import com.Ineb.Exception.DGuardPropertyException; + +import java.io.*; +import java.sql.*; + +public class MySQLDec { + + static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; + static final String DB_URL = "jdbc:mysql://192.168.100.211:3306/testdb"; + + static final String USERNAME = "ineb"; + static final String PASSWORD = "ineb1234"; + + public static void main(String[] args) { + DguardManager dm = null; + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rset=null; + + try{ + dm = DguardManager.Init("bidfunding", "Agent!1700", "Agent!1700", "/home/dguard/javaapi/conf/dguard.conf"); + + Class.forName(JDBC_DRIVER); + conn = DriverManager.getConnection(DB_URL,USERNAME,PASSWORD); + conn.setAutoCommit(false); + System.out.println("- MySQL Connection"); + + String selectSql = "SELECT seq, data FROM tbl01"; + pstmt = conn.prepareStatement(selectSql.toString()); + rset = pstmt.executeQuery(); + + while(rset.next()){ + int seq = rset.getInt("SEQ"); + String data01 = rset.getString("data"); + + String decdata01 = dm.Decrypt("TBL", "ENC", data01); + + System.out.print("SEQ : " + seq + "\n"); + System.out.print("DATA : " + data01 + "\n"); + System.out.print("DEC : " + decdata01 + "\n"); + } + + rset.close(); + pstmt.close(); + conn.close(); + }catch(SQLException se1){ + se1.printStackTrace(); + }catch(Exception ex){ + ex.printStackTrace(); + }finally{ + try{ + if(pstmt!=null) + pstmt.close(); + }catch(SQLException se2){ + } + try{ + if(conn!=null) + conn.close(); + }catch(SQLException se){ + se.printStackTrace(); + } + } + System.out.println("- MySQL Connection Close"); + } +} diff --git a/3rd-party/dguard/sample/mysql/MySQLEnc.class b/3rd-party/dguard/sample/mysql/MySQLEnc.class new file mode 100644 index 0000000..2182aad Binary files /dev/null and b/3rd-party/dguard/sample/mysql/MySQLEnc.class differ diff --git a/3rd-party/dguard/sample/mysql/MySQLEnc.java b/3rd-party/dguard/sample/mysql/MySQLEnc.java new file mode 100644 index 0000000..ad15883 --- /dev/null +++ b/3rd-party/dguard/sample/mysql/MySQLEnc.java @@ -0,0 +1,98 @@ +import com.Ineb.Dguard.*; +import com.Ineb.Exception.DguardLoginException; +import com.Ineb.Exception.DguardNetworkException; +import com.Ineb.Exception.DGuardPropertyException; + +import java.io.*; +import java.sql.*; + +public class MySQLEnc { + + static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; + static final String DB_URL = "jdbc:mysql://192.168.100.211:3306/testdb"; + + static final String USERNAME = "ineb"; + static final String PASSWORD = "ineb1234"; + + public static void main(String[] args) { + DguardManager dm = null; + + Connection conn = null; + PreparedStatement pstmt = null; + PreparedStatement updatePstmt = null; + ResultSet rset=null; + + try{ + dm = DguardManager.Init("bidfunding", "Agent!1700", "Agent!1700", "/home/dguard/javaapi/conf/dguard.conf"); + + Class.forName(JDBC_DRIVER); + conn = DriverManager.getConnection(DB_URL,USERNAME,PASSWORD); + conn.setAutoCommit(false); + System.out.println("- MySQL Connection"); + + String selectSql = "SELECT seq, data FROM tbl01"; + pstmt = conn.prepareStatement(selectSql.toString()); + rset = pstmt.executeQuery(); + + String updateSql = "UPDATE tbl01 SET data = ? WHERE seq = ?"; + updatePstmt = conn.prepareStatement(updateSql.toString()); + + int commitCnt = 0; + + while(rset.next()){ + int seq = rset.getInt("SEQ"); + String data01 = rset.getString("data"); + + String encdata01 = dm.Encrypt("TBL", "ENC", data01); + + System.out.print("SEQ : " + seq + "\n"); + System.out.print("DATA : " + data01 + "\n"); + System.out.print("ENC : " + encdata01 + "\n"); + + updatePstmt.setString(1, encdata01); + updatePstmt.setInt(2, seq); + + updatePstmt.addBatch(); + updatePstmt.clearParameters(); + + if ( commitCnt > 0 && commitCnt % 1000 == 0 ) { + updatePstmt.executeBatch(); + updatePstmt.clearBatch(); + conn.commit(); + + System.out.println(commitCnt + ", " + data01 + ", " + encdata01); + } + + commitCnt++; + } + + updatePstmt.executeBatch(); + conn.commit(); + conn.setAutoCommit(true); + + System.out.println("Commit count : " + commitCnt); + + rset.close(); + updatePstmt.close(); + pstmt.close(); + conn.close(); + }catch(SQLException se1){ + se1.printStackTrace(); + }catch(Exception ex){ + ex.printStackTrace(); + }finally{ + try{ + if(pstmt!=null) + pstmt.close(); + }catch(SQLException se2){ + } + try{ + if(conn!=null) + conn.close(); + }catch(SQLException se){ + se.printStackTrace(); + } + } + System.out.println("- MySQL Connection Close"); + } +} diff --git a/3rd-party/dguard/sample/mysql/com_mysqldec.sh b/3rd-party/dguard/sample/mysql/com_mysqldec.sh new file mode 100644 index 0000000..9917256 --- /dev/null +++ b/3rd-party/dguard/sample/mysql/com_mysqldec.sh @@ -0,0 +1,2 @@ +javac -classpath ../../lib/DguardAPI.jar:../../lib/INICrypto_v4.1.1.jar:../../lib/INISAFEPKI_v1.1.21.jar:../../lib/log4j-1.2.17.jar MySQLDec.java + diff --git a/3rd-party/dguard/sample/mysql/com_mysqlenc.sh b/3rd-party/dguard/sample/mysql/com_mysqlenc.sh new file mode 100644 index 0000000..bfd5d5b --- /dev/null +++ b/3rd-party/dguard/sample/mysql/com_mysqlenc.sh @@ -0,0 +1,2 @@ +javac -classpath ../../lib/DguardAPI.jar:../../lib/INICrypto_v4.1.1.jar:../../lib/INISAFEPKI_v1.1.21.jar:../../lib/log4j-1.2.17.jar MySQLEnc.java + diff --git a/3rd-party/dguard/sample/mysql/exec_mysqldec.sh b/3rd-party/dguard/sample/mysql/exec_mysqldec.sh new file mode 100644 index 0000000..a71a4fd --- /dev/null +++ b/3rd-party/dguard/sample/mysql/exec_mysqldec.sh @@ -0,0 +1,2 @@ +java -Xms64m -Xmx128m -classpath .:../../lib/DguardAPI.jar:../../lib/MagicJCrypto-v2.0.0.0.jar:../../lib/log4j-1.2.17.jar:../../lib/com.mysql.jdbc_5.1.5.jar MySQLDec + diff --git a/3rd-party/dguard/sample/mysql/exec_mysqlenc.sh b/3rd-party/dguard/sample/mysql/exec_mysqlenc.sh new file mode 100644 index 0000000..89851c2 --- /dev/null +++ b/3rd-party/dguard/sample/mysql/exec_mysqlenc.sh @@ -0,0 +1,2 @@ +java -Xms64m -Xmx128m -classpath .:../../lib/DguardAPI.jar:../../lib/MagicJCrypto-v2.0.0.0.jar:../../lib/log4j-1.2.17.jar:../../lib/com.mysql.jdbc_5.1.5.jar MySQLEnc + diff --git a/3rd-party/dguard/sample/pgsql/PGSQLDec.class b/3rd-party/dguard/sample/pgsql/PGSQLDec.class new file mode 100644 index 0000000..339e6ba Binary files /dev/null and b/3rd-party/dguard/sample/pgsql/PGSQLDec.class differ diff --git a/3rd-party/dguard/sample/pgsql/PGSQLDec.java b/3rd-party/dguard/sample/pgsql/PGSQLDec.java new file mode 100644 index 0000000..8b413ed --- /dev/null +++ b/3rd-party/dguard/sample/pgsql/PGSQLDec.java @@ -0,0 +1,68 @@ +import com.Ineb.Dguard.*; +import com.Ineb.Exception.DguardLoginException; +import com.Ineb.Exception.DguardNetworkException; +import com.Ineb.Exception.DGuardPropertyException; + +import java.io.*; +import java.sql.*; + +public class PGSQLDec { + + static final String DB_URL = "jdbc:postgresql://10.22.170.25:5432/miracle"; + + static final String USERNAME = "miracle"; + static final String PASSWORD = "q!fvYOP^evn"; + + public static void main(String[] args) { + DguardManager dm = null; + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rset=null; + + try{ + dm = DguardManager.Init("miraclefunding", "Agent!1700", "Agent!1700", "/home/inebsoft/javaapi/conf/dguard.conf"); + + conn = DriverManager.getConnection(DB_URL,USERNAME,PASSWORD); + conn.setAutoCommit(false); + System.out.println("- PostgreeSQL Connection"); + + String selectSql = "SELECT id, seyfert_guid FROM admin_model"; + pstmt = conn.prepareStatement(selectSql.toString()); + rset = pstmt.executeQuery(); + + while(rset.next()){ + int id = rset.getInt("id"); + String data01 = rset.getString("seyfert_guid"); + + System.out.print("ID : " + id + "\n"); + System.out.print("DATA : " + data01 + "\n"); + + String decdata01 = dm.Decrypt("TBL", "ENC", data01); + + System.out.print("DEC : " + decdata01 + "\n"); + } + + rset.close(); + pstmt.close(); + conn.close(); + }catch(SQLException se1){ + se1.printStackTrace(); + }catch(Exception ex){ + ex.printStackTrace(); + }finally{ + try{ + if(pstmt!=null) + pstmt.close(); + }catch(SQLException se2){ + } + try{ + if(conn!=null) + conn.close(); + }catch(SQLException se){ + se.printStackTrace(); + } + } + System.out.println("- PostgreeSQL Connection Close"); + } +} diff --git a/3rd-party/dguard/sample/pgsql/PGSQLEnc.java b/3rd-party/dguard/sample/pgsql/PGSQLEnc.java new file mode 100644 index 0000000..019a5a5 --- /dev/null +++ b/3rd-party/dguard/sample/pgsql/PGSQLEnc.java @@ -0,0 +1,96 @@ +import com.Ineb.Dguard.*; +import com.Ineb.Exception.DguardLoginException; +import com.Ineb.Exception.DguardNetworkException; +import com.Ineb.Exception.DGuardPropertyException; + +import java.io.*; +import java.sql.*; + +public class PGSQLEnc { + + static final String DB_URL = "jdbc:postgressql://127.0.0.1:5432/miracle"; + + static final String USERNAME = "miracle"; + static final String PASSWORD = "q!fvYOP^evn"; + + public static void main(String[] args) { + DguardManager dm = null; + + Connection conn = null; + PreparedStatement pstmt = null; + PreparedStatement updatePstmt = null; + ResultSet rset=null; + + try{ + dm = DguardManager.Init("miraclefunding", "Agent!1700", "Agent!1700", "/home/inebsoft/javaapi/conf/dguard.conf"); + + conn = DriverManager.getConnection(DB_URL,USERNAME,PASSWORD); + conn.setAutoCommit(false); + System.out.println("- PostgreeSQL Connection"); + + String selectSql = "SELECT seq, data FROM tbl01"; + pstmt = conn.prepareStatement(selectSql.toString()); + rset = pstmt.executeQuery(); + + String updateSql = "UPDATE tbl01 SET data = ? WHERE seq = ?"; + updatePstmt = conn.prepareStatement(updateSql.toString()); + + int commitCnt = 0; + + while(rset.next()){ + int seq = rset.getInt("SEQ"); + String data01 = rset.getString("data"); + + String encdata01 = dm.Encrypt("TBL", "ENC", data01); + + System.out.print("SEQ : " + seq + "\n"); + System.out.print("DATA : " + data01 + "\n"); + System.out.print("ENC : " + encdata01 + "\n"); + + updatePstmt.setString(1, encdata01); + updatePstmt.setInt(2, seq); + + updatePstmt.addBatch(); + updatePstmt.clearParameters(); + + if ( commitCnt > 0 && commitCnt % 1000 == 0 ) { + updatePstmt.executeBatch(); + updatePstmt.clearBatch(); + conn.commit(); + + System.out.println(commitCnt + ", " + data01 + ", " + encdata01); + } + + commitCnt++; + } + + updatePstmt.executeBatch(); + conn.commit(); + conn.setAutoCommit(true); + + System.out.println("Commit count : " + commitCnt); + + rset.close(); + updatePstmt.close(); + pstmt.close(); + conn.close(); + }catch(SQLException se1){ + se1.printStackTrace(); + }catch(Exception ex){ + ex.printStackTrace(); + }finally{ + try{ + if(pstmt!=null) + pstmt.close(); + }catch(SQLException se2){ + } + try{ + if(conn!=null) + conn.close(); + }catch(SQLException se){ + se.printStackTrace(); + } + } + System.out.println("- PostgreeSQL Connection Close"); + } +} diff --git a/3rd-party/dguard/sample/pgsql/com_pgsqldec.sh b/3rd-party/dguard/sample/pgsql/com_pgsqldec.sh new file mode 100644 index 0000000..3ecc1f1 --- /dev/null +++ b/3rd-party/dguard/sample/pgsql/com_pgsqldec.sh @@ -0,0 +1,2 @@ +javac -classpath ../../lib/DguardAPI.jar:../../lib/INICrypto_v4.1.1.jar:../../lib/INISAFEPKI_v1.1.21.jar:../../lib/log4j-1.2.17.jar PGSQLDec.java + diff --git a/3rd-party/dguard/sample/pgsql/com_pgsqlenc.sh b/3rd-party/dguard/sample/pgsql/com_pgsqlenc.sh new file mode 100644 index 0000000..03be4ce --- /dev/null +++ b/3rd-party/dguard/sample/pgsql/com_pgsqlenc.sh @@ -0,0 +1,2 @@ +javac -classpath ../../lib/DguardAPI.jar:../../lib/INICrypto_v4.1.1.jar:../../lib/INISAFEPKI_v1.1.21.jar:../../lib/log4j-1.2.17.jar PGSQLEnc.java + diff --git a/3rd-party/dguard/sample/pgsql/exec_pgsqldec.sh b/3rd-party/dguard/sample/pgsql/exec_pgsqldec.sh new file mode 100644 index 0000000..de1aada --- /dev/null +++ b/3rd-party/dguard/sample/pgsql/exec_pgsqldec.sh @@ -0,0 +1,2 @@ +java -Xms64m -Xmx128m -classpath .:../../lib/DguardAPI.jar:../../lib/MagicJCrypto-v2.0.0.0.jar:../../lib/log4j-1.2.17.jar:../../lib/postgresql-9.3-1100.jdbc4.jar PGSQLDec + diff --git a/3rd-party/dguard/sample/pgsql/exec_pgsqlenc.sh b/3rd-party/dguard/sample/pgsql/exec_pgsqlenc.sh new file mode 100644 index 0000000..e01d4c2 --- /dev/null +++ b/3rd-party/dguard/sample/pgsql/exec_pgsqlenc.sh @@ -0,0 +1,2 @@ +java -Xms64m -Xmx128m -classpath .:../../lib/DguardAPI.jar:../../lib/MagicJCrypto-v2.0.0.0.jar:../../lib/log4j-1.2.17.jar:../../lib/postgresql-9.3-1100.jdbc4.jar PGSQLEnc + diff --git a/3rd-party/dguard/sample/test.bat b/3rd-party/dguard/sample/test.bat new file mode 100644 index 0000000..e3f2ea3 --- /dev/null +++ b/3rd-party/dguard/sample/test.bat @@ -0,0 +1,2 @@ +java -classpath .;..\lib\SecureDriver.jar;..\lib\INICrypto_v4.0.4.jar;..\lib\INISAFEPKI_v1.1.0.jar;..\lib\tibero4-jdbc.jar APITest2 + diff --git a/3rd-party/dguard/sample/test.sh b/3rd-party/dguard/sample/test.sh new file mode 100644 index 0000000..725930b --- /dev/null +++ b/3rd-party/dguard/sample/test.sh @@ -0,0 +1,2 @@ +java -Xms64m -Xmx128m -classpath .:../lib/DguardAPI.jar:../lib/MagicJCrypto-v2.0.0.0.jar:../lib/log4j-1.2.17.jar: APITest2 + diff --git a/3rd-party/dguard/token/xit_agent.token b/3rd-party/dguard/token/xit_agent.token new file mode 100644 index 0000000..f542f9a --- /dev/null +++ b/3rd-party/dguard/token/xit_agent.token @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/3rd-party/echelon/MPowerCrypto2.0.sig b/3rd-party/echelon/MPowerCrypto2.0.sig new file mode 100644 index 0000000..dbf49f9 Binary files /dev/null and b/3rd-party/echelon/MPowerCrypto2.0.sig differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b03e659 --- /dev/null +++ b/pom.xml @@ -0,0 +1,192 @@ + + 4.0.0 + + cokr.xit.base + xit-crypto + 23.04.01-SNAPSHOT + jar + + xit-crypto + http://maven.apache.org + + + UTF-8 + + 17 + ${java.version} + ${java.version} + + 5.3.20 + 4.1.0 + + + + + mvn2s + https://repo1.maven.org/maven2/ + + true + + + true + + + + egovframe + https://maven.egovframe.go.kr/maven/ + + true + + + false + + + + maven-public + https://nas.xit.co.kr:8888/repository/maven-public/ + + + + + + + cokr.xit.base + xit-foundation + 23.04.01-SNAPSHOT + + + + org.egovframe.rte + org.egovframe.rte.fdl.crypto + ${org.egovframe.rte.version} + + + + 3rd-party + echelon + 2.5 + system + ${basedir}/3rd-party/echelon/EchelonClientV2.5.jar + + + + 3rd-party + dguard + 1.0 + system + ${basedir}/3rd-party/dguard/lib/DguardAPI.jar + + + + + + install + ${basedir}/target + ${project.artifactId}-${project.version} + + + ${basedir}/src/main/resources + + + + ${basedir}/src/test/resources + ${basedir}/src/main/resources + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + UTF-8 + + + + + org.codehaus.mojo + emma-maven-plugin + 1.0-alpha-3 + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.1 + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + **/*.class + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0 + + true + xml + + **/Abstract*.java + **/*Suite.java + + + **/*Test.java + + + + + org.codehaus.mojo + emma-maven-plugin + true + + + org.apache.maven.plugins + maven-source-plugin + 2.2 + + + attach-sources + + jar + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + + + + + + + maven-snapshot + https://nas.xit.co.kr:8888/repository/maven-snapshots/ + + + + maven-release + https://nas.xit.co.kr:8888/repository/maven-releases/ + + + + + \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/crypto/CryptoConfig.java b/src/main/java/cokr/xit/base/crypto/CryptoConfig.java new file mode 100644 index 0000000..71081a7 --- /dev/null +++ b/src/main/java/cokr/xit/base/crypto/CryptoConfig.java @@ -0,0 +1,38 @@ +package cokr.xit.base.crypto; + +import javax.annotation.Resource; + +import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import cokr.xit.base.crypto.Cryptography.Config; +import cokr.xit.base.crypto.web.CleanupCryptography; +import cokr.xit.foundation.util.ConditionSupport; + +@EnableWebMvc +@Configuration +@Conditional(ConditionSupport.InBoot.class) +public class CryptoConfig implements WebMvcConfigurer { + @Resource(name = "sqlSession") + private DefaultSqlSessionFactory sqlSessionFactory; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new CleanupCryptography()).addPathPatterns(new String[] {"/", "/**/*.do"}); + } + + @Bean + CryptographySupport cryptographySupport() { + Config config = Cryptography.Config.get(); + if (!config.isEnabled()) return null; + + CryptographySupport plugin = new CryptographySupport(); + sqlSessionFactory.getConfiguration().addInterceptor(plugin); + return plugin; + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/crypto/Cryptography.java b/src/main/java/cokr/xit/base/crypto/Cryptography.java new file mode 100644 index 0000000..c0a03f8 --- /dev/null +++ b/src/main/java/cokr/xit/base/crypto/Cryptography.java @@ -0,0 +1,355 @@ +package cokr.xit.base.crypto; + +import java.io.InputStream; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; + +import org.apache.commons.beanutils.PropertyUtils; +import org.springframework.core.io.ClassPathResource; + +import cokr.xit.foundation.AbstractComponent; +import cokr.xit.foundation.data.DataObject; +import cokr.xit.foundation.data.JSON; + +/**암복호화를 위한 베이스 클래스. + * 암복호화 지원 클래스는 {@link Config 설정파일에서 설정정보}를 읽어들인다. + * @author mjkhan + */ +public abstract class Cryptography extends AbstractComponent { + /** 암복호화 설정정보 */ + protected CryptoDef def; + + /**새 Cryptography을(를) 생성한다. + * @param name 암복호화 설정이름 + */ + protected Cryptography(String name) { + def = Config.conf + .getCryptoDef(notEmpty(name, "name")) + .checkConsistency(getClass()); + try { + init(); + } catch (Exception e) { + throw runtimeException(e); + } + } + + /**현재 암복호화 지원 객체의 설정이름을 반환한다. + * @return 암복호화 설정이름 + */ + public String name() { + return def != null ? def.name : null; + } + + /**현재 암복호화 지원 객체를 초기화한다. + * {@link #def 암복호화 설정정보}를 읽어들인 후 실행 + * @throws Exception + */ + protected void init() throws Exception {} + + /**주어진 평문문자열을 암호화하여 반환한다. + * @param plain 평문문자열 + * @return 암호화한 문자열 + */ + public String encrypt(String plain) { + if (isEmpty(plain)) return plain; + try { + return doEncrypt(plain); + } catch (Exception e) { + throw runtimeException(e); + } + } + + /**평문문자열의 암호화를 실행한다. + * @param plain 평문문자열 + * @return 암호화한 문자열 + * @throws Exception + */ + protected abstract String doEncrypt(String plain) throws Exception; + + /**{@link #encrypt(String) encrypt((String)obj)}를 실행한다. + * @param obj 평문문자열 + * @return 암호화한 문자열 + */ + public String encrypt(Object obj) { + return encrypt((String)obj); + } + + /**암호화된 문자열을 복호화하여 반환한다. + * @param encrypted 암호화된 문자열 + * @return 복호화한 문자열 + */ + public String decrypt(String encrypted) { + if (isEmpty(encrypted)) return encrypted; + + try { + return doDecrypt(encrypted); + } catch (Exception e) { + throw runtimeException(e); + } + } + + /**암호화된 문자열의 복호화를 실행한다. + * @param encrypted 암호화된 문자열 + * @return 복호화한 문자열 + * @throws Exception + */ + protected abstract String doDecrypt(String encrypted) throws Exception; + + /**{@link #decrypt(String) decrypt((String)obj)}를 실행한다. + * @param obj 암호화된 문자열 + * @return 복호화한 문자열 + */ + public String decrypt(Object obj) { + return decrypt((String)obj); + } + + /**암복호화 지원클래스 설정정보 + * @author mjkhan + */ + public static class CryptoDef { + private String name; + private Class klass; + private DataObject settings; + + /**이름을 반환한다. + * @return 이름 + */ + public String getName() { + return name; + } + + /**이름을 설정한다. + * @param name 이름 + */ + public void setName(String name) { + this.name = name; + } + + private CryptoDef checkConsistency(Class klass) { + if (!this.klass.equals(klass)) + throw new RuntimeException(klass.getName() + " is not consistent with the Definition '" + name + "'"); + return this; + } + + /**현재 설정정보로 암복호화 지원객체를 생성하여 반환한다. + * @return 암복호화 지원객체 + */ + public Cryptography newCrypto() { + try { + return (Cryptography)klass + .getConstructor(String.class) + .newInstance(name); + } catch (Exception e) { + throw runtimeException(e); + } + } + + /**클래스 이름을 설정한다. + * @param className 클래스 이름 + */ + public void setClass(String className) { + try { + this.klass = Class.forName(className); + } catch (Exception e) { + throw runtimeException(e); + } + } + + /**설정을 반환한다. + * @return settings + */ + public DataObject settings() { + return settings; + } + + /**설정항목을 설정한다. + * @param settings 설정항목 + */ + public void setSettings(DataObject settings) { + this.settings = settings; + } + } + + /**암복호화 대상데이터 유형 + * @author mjkhan + */ + public static class TargetValue { + private String name; + private Set + mapKeys, + objectProperties, + cryptoDefs; + + /**이름을 반환한다. + * @return 이름 + */ + public String getName() { + return name; + } + + /**이름을 설정한다. + * @param name 이름 + */ + public void setName(String name) { + this.name = name; + } + + /**맵에 포함된 대상데이터의 키를 반환한다. + * @return 맵에 포함된 대상데이터의 키 + */ + public Set getMapKeys() { + return ifEmpty(mapKeys, Collections::emptySet); + } + + /**맵에 포함된 대상데이터의 키를 설정한다. + * @param mapKeys 맵에 포함된 대상데이터의 키 + */ + public void setMapKeys(Set mapKeys) { + this.mapKeys = mapKeys; + } + + /**객체가 갖는 대상데이터의 프로퍼티를 반환한다. + * @return 객체가 갖는 대상데이터의 프로퍼티 + */ + public Set getObjectProperties() { + return ifEmpty(objectProperties, Collections::emptySet); + } + + /**객체가 갖는 대상데이터의 프로퍼티를 설정한다. + * @param objectProperties 객체가 갖는 대상데이터의 프로퍼티 + */ + public void setObjectProperties(Set objectProperties) { + this.objectProperties = objectProperties; + } + + /**암복호화 설정이름을 반환한다. + * @return 암복호화 설정이름 + */ + public Set getCryptoDefs() { + return ifEmpty(cryptoDefs, Collections::emptySet); + } + + /**암복호화 설정이름을 설정한다. + * @param cryptoDefs 암복호화 설정이름 + */ + public void setCryptoDefs(Set cryptoDefs) { + this.cryptoDefs = cryptoDefs; + } + } + + /**암복호화 지원클래스와 대상데이터의 설정정보. + * 클래스패스에 있는 xit-crypto.conf 파일에서 설정정보를 읽어들인다. + * @author mjkhan + */ + public static class Config { + private static Config conf; + + static { + try (InputStream input = new ClassPathResource("xit-crypto.conf").getInputStream()) { + conf = new JSON().parse(input, Config.class); + } catch (Exception e) { + throw runtimeException(e); + } + } + + public static Config get() { + return conf; + } + + private boolean enabled = true; + private List cryptoDefs; + private List targetValues; + + /**활성화 여부를 반환한다. + * @return 활성화 여부 + *
  • 활성화되어 있으면 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ + public boolean isEnabled() { + return enabled; + } + + /**활성화 여부를 설정한다. + * @param enabled 활성화 여부 + *
  • 활성화하려면 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + /**valueTypes을(를) 반환한다. + * @return valueTypes + */ + public List getTargetValues(Predicate test) { + return + targetValues == null ? Collections.emptyList() : + test == null ? targetValues : + targetValues.stream().filter(test).toList(); + } + + public List getTargetValues(Object obj) { + Predicate filter = valueType -> { + if (obj instanceof Map) { + Map map = (Map)obj; + for (String key: valueType.getMapKeys()) { + if (map.containsKey(key)) + return true; + } + return false; + } else { + for (String property: valueType.getObjectProperties()) { + if (PropertyUtils.isReadable(obj, property) + && PropertyUtils.isWriteable(obj, property) + ) + return true; + } + return false; + } + }; + return getTargetValues(filter); + } + + /**valueTypes을(를) 설정한다. + * @param targetValues valueTypes + */ + public void setTargetValues(List targetValues) { + this.targetValues = targetValues; + } + + /**cryptos을(를) 반환한다. + * @return cryptos + */ + public List getCryptoDefs(Predicate test) { + return + cryptoDefs == null ? Collections.emptyList() : + test == null ? cryptoDefs : + cryptoDefs.stream().filter(test).toList(); + } + + public CryptoDef getCryptoDef(String name) { + List defs = getCryptoDefs(def -> name.equals(def.name)); + if (defs.isEmpty()) + throw new NullPointerException("CryptoDef not found named '" + name + "'"); + return defs.get(0); + } + + /**cryptos을(를) 설정한다. + * @param cryptoDefs cryptos + */ + public void setCryptoDefs(List cryptoDefs) { + this.cryptoDefs = cryptoDefs; + } + + public List newCryptos() { + return getCryptoDefs(null).stream() + .map(CryptoDef::newCrypto) + .toList(); + } + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/crypto/CryptographySupport.java b/src/main/java/cokr/xit/base/crypto/CryptographySupport.java new file mode 100644 index 0000000..6108935 --- /dev/null +++ b/src/main/java/cokr/xit/base/crypto/CryptographySupport.java @@ -0,0 +1,143 @@ +package cokr.xit.base.crypto; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.ibatis.executor.parameter.ParameterHandler; +import org.apache.ibatis.executor.resultset.ResultSetHandler; +import org.apache.ibatis.plugin.Intercepts; +import org.apache.ibatis.plugin.Signature; + +import cokr.xit.base.crypto.Cryptography.Config; +import cokr.xit.foundation.data.paging.MybatisPlugin; + +/**데이터베이스와 주고받는 파라미터와 데이터를 암복호화하는 마이바티스 플러그인. + * @author mjkhan + */ +@Intercepts({ + @Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}), + @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}) +}) +public class CryptographySupport extends MybatisPlugin { + private static final ThreadLocal> cached = new ThreadLocal<>(); + + private static boolean isCached(Object obj) { + List objs = cached.get(); + return objs != null ? objs.contains(obj) : false; + } + + private static void setCache(Object obj) { + List objs = cached.get(); + if (objs == null) + cached.set(objs = new ArrayList<>()); + objs.add(obj); + } + + public static void clear() { + List objs = cached.get(); + if (objs != null) + objs.clear(); + cached.remove(); + } + + private Map cryptos; + + public CryptographySupport() { + Config config = Cryptography.Config.get(); + if (!config.isEnabled()) return; + + setCryptos(config.newCryptos()); + } + + private void setCryptos(List cryptos) { + this.cryptos = cryptos.stream().collect(Collectors.toMap(Cryptography::name, crypto -> crypto)); + } + + @Override + protected Object setParameters(ParameterHandler parameterHandler, PreparedStatement statement) throws SQLException { + Object obj = parameterHandler.getParameterObject(); + encrypt(obj); + return super.setParameters(parameterHandler, statement); + } + + @Override + protected Object handle(ResultSetHandler resultSetHandler, Statement statement) throws SQLException { + Object obj = super.handle(resultSetHandler, statement); + + if (obj instanceof List) { + List list = (List)obj; + list.forEach(this::decrypt); + } else { + decrypt(obj); + } + + return obj; + } + + private boolean isEnabled(Object obj) { + return !isEmpty(obj) + && !isEmpty(cryptos); + } + + private void encrypt(Object obj) { + if (!isEnabled(obj)) return; + + process(obj, (arg) -> convert(arg, (crypto, val) -> crypto.encrypt(val), true)); + } + + private void convert(Object obj, BiFunction converter, boolean cache) { + List targetValues = Cryptography.Config.get().getTargetValues(obj); + if (targetValues.isEmpty()) return; + + try { + if (cache && isCached(obj)) return; + + for (Cryptography.TargetValue target: targetValues) { + for (String cryptoDef: target.getCryptoDefs()) { + Cryptography crypto = cryptos.get(cryptoDef); + if (crypto == null) continue; + + if (obj instanceof Map) { + Map map = (Map)obj; + target.getMapKeys().stream() + .filter(key -> map.containsKey(key)) + .forEach(key -> { + Object val = map.get(key); + map.put(key, converter.apply(crypto, val)); + }); + } else { + target.getObjectProperties().stream() + .filter(property -> PropertyUtils.isReadable(obj, property)) + .forEach(property -> { + try { + String val = BeanUtils.getProperty(obj, property); + BeanUtils.setProperty(obj, property, converter.apply(crypto, val)); + } catch (Exception e) { + throw runtimeException(e); + } + }); + } + } + } + + if (cache) + setCache(obj); + } catch (Exception e) { + throw runtimeException(e); + } + } + + private void decrypt(Object obj) { + if (!isEnabled(obj)) return; + + convert(obj, (crypto, val) -> crypto.decrypt(val), false); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/crypto/bean/ARIA.java b/src/main/java/cokr/xit/base/crypto/bean/ARIA.java new file mode 100644 index 0000000..aff71c5 --- /dev/null +++ b/src/main/java/cokr/xit/base/crypto/bean/ARIA.java @@ -0,0 +1,115 @@ +package cokr.xit.base.crypto.bean; + +import java.util.Base64; + +import org.egovframe.rte.fdl.cryptography.EgovPasswordEncoder; +import org.egovframe.rte.fdl.cryptography.impl.EgovARIACryptoServiceImpl; + +import cokr.xit.base.crypto.Cryptography; + +/**전자정부 프레임워크의 ARIA 서비스로 암복호화를 지원하는 클래스 + * @author mjkhan + */ +public class ARIA extends Cryptography { + private String + key, + algorithm; + private int blockSize; + + private EgovPasswordEncoder passwordEncoder; + private EgovARIACryptoServiceImpl aria; + + public ARIA(String name) { + super(name); + } + + /**키를 반환한다. + * @return 키 + */ + public String getKey() { + return ifEmpty(key, () -> key = def.settings().string("key")); + } + + /**키를 설정한다. + * @param key 키 + * @return 현재 ARIA + */ + public ARIA setKey(String key) { + this.key = key; + return this; + } + + /**알고리즘을 반환한다. 디폴트는 SHA-256. + * @return 알고리즘 + */ + public String getAlgorithm() { + return ifEmpty(algorithm, () -> algorithm = def.settings().string("algorithm")); + } + + /**알고리즘을 설정한다. 디폴트는 SHA-256. + * @param algorithm 알고리즘 + * @return 현재 ARIA + */ + public ARIA setAlgorithm(String algorithm) { + this.algorithm = algorithm; + return this; + } + + /**블록사이즈를 반환한다. 디폴트는 1024. + * @return 블록사이즈 + */ + public int getBlockSize() { + return blockSize > 0 ? blockSize : (blockSize = def.settings().number("blockSize").intValue()); + } + + /**블록사이즈를 설정한다. 디폴트는 1024. + * @param blockSize 블록사이즈 + * @return 현재 ARIA + */ + public ARIA setBlockSize(int blockSize) { + this.blockSize = blockSize; + return this; + } + + @Override + protected String doEncrypt(String plain) { + byte[] bytes = service().encrypt(plain.getBytes(), key); + return Base64.getEncoder().encodeToString(bytes); + } + + private EgovPasswordEncoder passwordEncoder() { + if (passwordEncoder == null) { + passwordEncoder = new EgovPasswordEncoder(); + String hashed = passwordEncoder.encryptPassword(getKey()); + passwordEncoder.setHashedPassword(hashed); + passwordEncoder.setAlgorithm(getAlgorithm()); + } + return passwordEncoder; + } + + private EgovARIACryptoServiceImpl service() { + if (aria == null) { + aria = new EgovARIACryptoServiceImpl(); + aria.setPasswordEncoder(passwordEncoder()); + aria.setBlockSize(getBlockSize()); + } + return aria; + } + + @Override + protected String doDecrypt(String encrypted) { + byte[] bytes = Base64.getDecoder().decode(encrypted); + return new String(service().decrypt(bytes, key)); + } + + /**현재 설정상태를 비운다. + * @return 현재 ARIA + */ + public ARIA clear() { + key = algorithm = null; + blockSize = 0; + passwordEncoder = null; + aria = null; + return this; + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/crypto/bean/DGuard.java b/src/main/java/cokr/xit/base/crypto/bean/DGuard.java new file mode 100644 index 0000000..e985e89 --- /dev/null +++ b/src/main/java/cokr/xit/base/crypto/bean/DGuard.java @@ -0,0 +1,41 @@ +package cokr.xit.base.crypto.bean; + +import com.Ineb.Dguard.DguardManager; + +import cokr.xit.base.crypto.Cryptography; + +/**dguard로 암복호화를 지원하는 클래스 + * @author mjkhan + */ +public class DGuard extends Cryptography { + private DguardManager dguard; + private String + table, + column; + + public DGuard(String name) { + super(name); + } + + @Override + protected void init() throws Exception { + dguard = DguardManager.Init( + def.settings().string("secureID"), + def.settings().string("securePWD"), + def.settings().string("securePIN"), + def.settings().string("propertyPath") + ); + table = def.settings().string("tableName"); + column = def.settings().string("columnName"); + } + + @Override + protected String doEncrypt(String plain) throws Exception { + return dguard.Encrypt(table, column, plain); + } + + @Override + protected String doDecrypt(String encrypted) throws Exception { + return dguard.Decrypt(table, column, encrypted); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/crypto/bean/Echelon.java b/src/main/java/cokr/xit/base/crypto/bean/Echelon.java new file mode 100644 index 0000000..54ac24e --- /dev/null +++ b/src/main/java/cokr/xit/base/crypto/bean/Echelon.java @@ -0,0 +1,36 @@ +package cokr.xit.base.crypto.bean; + +import cokr.xit.base.crypto.Cryptography; +import xw.plf.echelon.clientx.CipherBroker; + +/**echelon으로 암복호화를 지원하는 클래스 + * @author mjkhan + */ +public class Echelon extends Cryptography { + private static boolean ready; + + public Echelon(String name) { + super(name); + } + + @Override + public void init() { + if (ready) return; + + System.setProperty("CRYPTO.MODULE", def.settings().string("module")); + System.setProperty("ECHELON_AGENT_IP", def.settings().string("agentIP")); + System.setProperty("ECHELON_AGENT_PORT", def.settings().string("agentPort")); + + ready = true; + } + + @Override + protected String doEncrypt(String plain) { + return CipherBroker.eclEncrypt(plain); + } + + @Override + protected String doDecrypt(String encrypted) { + return CipherBroker.eclDecrypt(encrypted); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/crypto/web/CleanupCryptography.java b/src/main/java/cokr/xit/base/crypto/web/CleanupCryptography.java new file mode 100644 index 0000000..49305f2 --- /dev/null +++ b/src/main/java/cokr/xit/base/crypto/web/CleanupCryptography.java @@ -0,0 +1,22 @@ +package cokr.xit.base.crypto.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cokr.xit.base.crypto.CryptographySupport; +import cokr.xit.foundation.web.RequestInterceptor; + +/**암호화한 데이터를 갖는 객체들의 캐시를 비우는 RequestInterceptor + * @author mjkhan + */ +public class CleanupCryptography extends RequestInterceptor { + @Override + public void afterCompletion(HttpServletRequest hreq, HttpServletResponse hresp, Object handler, Exception ex) throws Exception { + CryptographySupport.clear(); + } + + @Override + public void afterConcurrentHandlingStarted(HttpServletRequest hreq, HttpServletResponse hresp, Object handler) throws Exception { + CryptographySupport.clear(); + } +} \ No newline at end of file diff --git a/src/main/resources/xit-crypto.conf b/src/main/resources/xit-crypto.conf new file mode 100644 index 0000000..592afc6 --- /dev/null +++ b/src/main/resources/xit-crypto.conf @@ -0,0 +1,39 @@ +{ "enabled": true, + "cryptoDefs": [ /* 암복호화 지원 클래스별 설정. 사용하지 않는 설정은 제거할 것. */ + { "name": "aria", + "class": "cokr.xit.base.crypto.bean.ARIA", + "settings": { + "key": "Copyright (c) 2015 - (주)엑스아이티", + "algorithm": "SHA-256", + "blockSize": 1024 + } + }, + { "name": "echelon", + "class": "cokr.xit.base.crypto.bean.Echelon", + "settings": { + "module": "3rd-party/echelon", // echelon 라이브러리 파일 디렉토리 경로 + "agentIP": "211.119.124.117", + "agentPort": 29995 + } + }, + { "name": "dguard", + "class": "cokr.xit.base.crypto.bean.DGuard", + "settings": { + "secureID": "xit_agent", + "securePWD": "Agent!@#$5", + "securePIN": "Agent!@#$5", + "propertyPath": "3rd-party/dguard/conf/dguard.conf", // dguard 설정파일 경로 + "tableName": "TB_PAYER", + "columnName": "RTPYR_NO" + } + } + ], + + "targetValues": [ /* 암복호화 대상데이터 설정 */ + { "name": "주민등록번호", + "mapKeys": ["RTPYR_NO", "rtpyrNo"], + "objectProperties": ["rtpyrNo"], + "cryptoDefs": ["aria"] // 암복호화 지원 클래스 설정 이름 + } + ] +} \ No newline at end of file diff --git a/src/test/java/cokr/xit/base/crypto/CryptographyTest.java b/src/test/java/cokr/xit/base/crypto/CryptographyTest.java new file mode 100644 index 0000000..b1dfcd8 --- /dev/null +++ b/src/test/java/cokr/xit/base/crypto/CryptographyTest.java @@ -0,0 +1,171 @@ +package cokr.xit.base.crypto; + +import java.lang.reflect.Method; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.beanutils.PropertyUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import cokr.xit.base.crypto.bean.ARIA; +import cokr.xit.base.crypto.bean.DGuard; +import cokr.xit.base.crypto.bean.Echelon; + +public class CryptographyTest /* extends TestSupport */ { + private String + text = "뿌리깊은 나무", + numeric = "1234567890123"; + + @Test + void configuration() { + Cryptography.Config conf = Cryptography.Config.get(); + + conf.getCryptoDefs(null).forEach(crypto -> { + System.out.println("========== cryptoDef '" + crypto.getName() + "' =========="); + crypto.settings().forEach((k, v) -> System.out.println(k + " -> " + v)); + }); + + conf.getTargetValues(null).forEach(valueType -> { + System.out.println("========== valueType '" + valueType.getName() + "' =========="); + System.out.println("valueType mapKeys" + valueType.getMapKeys()); + System.out.println("cryptoDefs: " + valueType.getCryptoDefs()); + }); + } + + @Test + void aria() { + String name = "aria"; + ARIA aria = new ARIA(name); + Assertions.assertEquals(name, aria.name()); + + String encrypted = aria.encrypt(text), + decrypted = aria.decrypt(encrypted); + Assertions.assertEquals(text, decrypted); + System.out.println(String.format("text:%s -> encrypted:%s -> decrypted:%s", text, encrypted, decrypted)); + + encrypted = aria.encrypt(numeric); + decrypted = aria.decrypt(encrypted); + Assertions.assertEquals(numeric, decrypted); + System.out.println(String.format("text:%s -> encrypted:%s -> decrypted:%s", numeric, encrypted, decrypted)); + } + + @Test + void echelon() { + String name = "echelon"; + Echelon echelon = new Echelon(name); + Assertions.assertEquals(name, echelon.name()); + + String encrypted = echelon.encrypt(text), + decrypted = echelon.decrypt(encrypted); + Assertions.assertEquals(text, decrypted); + System.out.println(String.format("text:%s -> encrypted:%s -> decrypted:%s", text, encrypted, decrypted)); + + encrypted = echelon.encrypt(numeric); + decrypted = echelon.decrypt(encrypted); + Assertions.assertEquals(numeric, decrypted); + System.out.println(String.format("text:%s -> encrypted:%s -> decrypted:%s", numeric, encrypted, decrypted)); + } + + @Test + void dguard() { + String name = "dguard"; + DGuard dguard = new DGuard(name); + Assertions.assertEquals(name, dguard.name()); + + String encrypted = dguard.encrypt(text), + decrypted = dguard.decrypt(encrypted); + Assertions.assertEquals(text, decrypted); + System.out.println(String.format("text:%s -> encrypted:%s -> decrypted:%s", text, encrypted, decrypted)); + + encrypted = dguard.encrypt(numeric); + decrypted = dguard.decrypt(encrypted); + Assertions.assertEquals(numeric, decrypted); + System.out.println(String.format("text:%s -> encrypted:%s -> decrypted:%s", numeric, encrypted, decrypted)); + } + + @Test + void newCryptos() { + Cryptography.Config conf = Cryptography.Config.get(); + + conf.newCryptos().forEach(crypto -> { + System.out.println("========== " + crypto.name() + " =========="); + String encrypted = crypto.encrypt(text), + decrypted = crypto.decrypt(encrypted); + Assertions.assertEquals(text, decrypted); + System.out.println(String.format("text:%s -> encrypted:%s -> decrypted:%s", text, encrypted, decrypted)); + + encrypted = crypto.encrypt(numeric); + decrypted = crypto.decrypt(encrypted); + Assertions.assertEquals(numeric, decrypted); + System.out.println(String.format("text:%s -> encrypted:%s -> decrypted:%s", numeric, encrypted, decrypted)); + }); + } + + @Test + void objectMethod() { + Class klass = MyObject.class; + try { + String val = "1234567890"; + Method setter = klass.getMethod("setRegNo", String.class); + + Object obj = new MyObject(); + setter.invoke(obj, val); + + Method getter = klass.getMethod("getRegNo", (Class[])null); + Object val2 = getter.invoke(obj); + + Assertions.assertEquals(val, val2); + System.out.println(String.format("%s, %s", val, val2)); + + System.out.println("instance: " + klass.isInstance(obj)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + void objectMethod2() { + String val = "1234567890", + getter = "getRegNo", + setter = "setRegNo"; + Object obj = new MyObject(); + Class klass = obj.getClass(); + } + + public static class MyObject { + private String regNo; + + /**regNo을(를) 반환한다. + * @return regNo + */ + public String getRegNo() { + return regNo; + } + + /**regNo을(를) 설정한다. + * @param regNo regNo + */ + public void setRegNo(String regNo) { + this.regNo = regNo; + } + + public MyObject getRequest() { + return this; + } + } + + @Test + void properties() { + MyObject obj = new MyObject(); + try { + String property = "request.regNo"; + boolean found = PropertyUtils.isReadable(obj, property) && PropertyUtils.isWriteable(obj, property); + if (found) { + BeanUtils.setProperty(obj, property, "1234567890123"); + System.out.println(BeanUtils.getProperty(obj, property)); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/test/resources/spring/context-common.xml b/src/test/resources/spring/context-common.xml new file mode 100644 index 0000000..e2269c6 --- /dev/null +++ b/src/test/resources/spring/context-common.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + classpath:message/message-common + classpath:message/authentication-message + classpath:org/egovframe/rte/fdl/property/messages/properties + + + + + 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sql/mapper/base/test-mapper.xml b/src/test/resources/sql/mapper/base/test-mapper.xml new file mode 100644 index 0000000..8a897ec --- /dev/null +++ b/src/test/resources/sql/mapper/base/test-mapper.xml @@ -0,0 +1,15 @@ + + + + + + +${sql} + +${sql} + +${sql} + +COMMIT + + \ No newline at end of file diff --git a/src/test/resources/sql/mapper/base/utility.xml b/src/test/resources/sql/mapper/base/utility.xml new file mode 100644 index 0000000..7f335db --- /dev/null +++ b/src/test/resources/sql/mapper/base/utility.xml @@ -0,0 +1,37 @@ + + + + + + +SELECT QROWS.* FROM ( + SELECT ROW_NUMBER() OVER() ROW_NUM + , COUNT(*) OVER() TOT_CNT, QBODY.* + FROM ( + + ) QBODY + ) QROWS +WHERE ROW_NUM BETWEEN ((#{pageNum} - 1) * #{fetchSize}) + 1 AND (#{pageNum} * #{fetchSize}) + + + +ORDER BY ${orderBy} + + + +DATE_FORMAT(CURRENT_TIMESTAMP, '%Y%m%d%H%i%s') +TO_CHAR(CURRENT_TIMESTAMP, 'YYYYMMDDHH24MISS') + +SELECTNOW FROM DUAL + +DATE_FORMAT(CURRENT_DATE, '%Y%m%d') +TO_CHAR(CURRENT_DATE, 'YYYYMMDD') + +SELECTTODAY FROM DUAL + +NVL(#{thisDay},) + +SELECTTHIS_DAY FROM DUAL + + \ No newline at end of file diff --git a/src/test/resources/sql/mybatis-config.xml b/src/test/resources/sql/mybatis-config.xml new file mode 100644 index 0000000..44b3157 --- /dev/null +++ b/src/test/resources/sql/mybatis-config.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file