Java Security/AES with JDBC
AES Encrypt, Decrype with JDBC
Soul-Learner
2014. 8. 18. 14:00
AES 알고리듬을 이용하여 평문을 암호화하고 데이터베이스에 저장 및 추출하는 예
관련참조
암호화된 데이터를 저장할 데이터베이스 테이블의 구조
암호화된 데이터는 byte[] 형으로 표현되므로 BLOB 형의 컬럼을 생성하여 byte[]을 저장할 수 있도록 한다
CREATE TABLE ENC_TB ( NUM NUMBER, ENC_DATA BLOB )
AES알고리듬을 이용하여 암호화 복호화 및 데이터베이스 입출력 예제 완전한 코드
암호화된 데이터를 Base64 인코딩/디코딩 기능도 포함되어 있으므로 웹사이트 제작시에도 참조하면 된다
사용된 Base64클래스 라이브러리
package org.kdea.java.security; import java.security.Key; import java.sql.*; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; public class AES_DB_Test { private Connection getConn() { Connection conn; String jdbc_driver = "oracle.jdbc.OracleDriver"; String db_url = "jdbc:oracle:thin:@localhost:1521:XE"; try{ Class.forName(jdbc_driver); conn = DriverManager.getConnection(db_url,"scott","tiger"); return conn; }catch(Exception e){ e.printStackTrace(); }finally { } return null; } /** * 평문을 파라미터로 받아서 AES 암호화한 후에 byte[]을 데이터베이스에 저장하고 성공여부를 리턴함 * @param plainStr AES 알고리즘으로 암호화하기 위한 평문 * @return 암호화된 데이터(byte[])를 데이터베이스에 성공적으로 저장했는지 여부(true, false) */ public boolean insertEncStr (String plainStr) { String key = "Bar12345Bar12345"; // 128 bit key Connection conn = null; PreparedStatement pstmt = null; try { // Create key and cipher Key aesKey = new SecretKeySpec(key.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES"); // encrypt the text cipher.init(Cipher.ENCRYPT_MODE, aesKey); byte[] encrypted = cipher.doFinal(plainStr.getBytes()); // 필요하다면 아래처럼 Base64 문자열로 인코딩하여 웹상의 URL 등에서도 사용할 수 있다 String base64Str = Base64Enc(encrypted); System.out.println("Base64 인코딩 문자열="+base64Str); // Base64 인코딩된 문자열을 다시 원래의 byte[]형으로 복원하려면... byte[] decodedBytes = Base64Dec(base64Str); System.out.println("Base64디코딩 결과="+Arrays.equals(encrypted, decodedBytes)); String enc_str = new String(encrypted); System.out.println("암호화 결과="+enc_str); String sql = "insert into enc_tb (num, enc_data) values (1,?)"; conn = getConn(); pstmt = conn.prepareStatement(sql); pstmt.setBytes(1, encrypted); int n = pstmt.executeUpdate(); return n>0 ? true : false; } catch (Exception e) { e.printStackTrace(); } finally{ try { pstmt.close(); conn.close(); } catch (SQLException e) { } } return false; } /** * 데이터베이스의 BLOB 컬럼에 저장된 암호화된 데이터를 추출하여 복호화하고 원래 문자열로 인코딩하여 리턴함 * @return 복호화하고 원래 문자열로 인코딩된 문자열 */ public String getEncStr() { String key = "Bar12345Bar12345"; // 128 bit key Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { String sql = "select * from enc_tb where num=1"; conn = getConn(); pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); if(rs.next()) { byte[] encrypted = rs.getBytes("ENC_DATA"); Key aesKey = new SecretKeySpec(key.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES"); // decrypt the text cipher.init(Cipher.DECRYPT_MODE, aesKey); String decrypted = new String(cipher.doFinal(encrypted)); System.out.println("복호화된 결과:" + decrypted); return decrypted; } } catch (Exception e) { e.printStackTrace(); } finally{ try { rs.close(); pstmt.close(); conn.close(); } catch (SQLException e) { } } return null; } // 암호화된 데이터(byte[]형)를 받아서 Base64문자열로 인코딩하여 리턴한다 private String Base64Enc(byte[] encrypted) { Base64 base64 = new Base64(); String base64Str = new String(base64.encode(encrypted)); return base64Str; } // Base64인코딩된 문자열을 원래의 데이터(byte[]형)로 디코딩한다 private byte[] Base64Dec(String base64Str) { Base64 base64 = new Base64(); byte[] restoredBytes = base64.decode(base64Str.getBytes()); return restoredBytes; } /** * 위의 기능을 테스트하기 위한 main 메소드 * @param args */ public static void main(String[] args) { AES_DB_Test app = new AES_DB_Test(); //암호화, DB저장, DB출력, 복호화 수행 테스트 String plainText = "Test 문자열 123"; //평문을 암호화하여 DB에 byte[] 형으로 저장함 app.insertEncStr(plainText); //DB에 저장된 암호화된 데이터를 byte[] 형으로 추출하고 복호화하여 원래의 문자열로 복원함 String db_out = app.getEncStr(); //원래의 문자열을 암호화, DB저장, DB출력, 복호화, 문자열화 과정을 거친후 //최종적인 문자열과 원래의 문자열을 비교하여 동일한지 테스트한다 System.out.println("복호화결과 원래의 데이터와 동일성 여부="+plainText.equals(db_out)); } }