2014-04-01

Oracle 9i SHA-256알고리즘 데이터 암호화 적용절차.



1. 아래의 사이트에서 오라클 9I에 적용된 Oracle JVM JDK1.3 버젼에 맞는 확장 라이브러리를 다운로드 받는다.
    
      http://www.bouncycastle.org/latest_releases.html

       >>> http://www.bouncycastle.org/download/jce-jdk13-150.jar

       >>> http://www.bouncycastle.org/download/jce-ext-jdk13-150.jar

2. LoadJava 툴을 이용하여 다운로드 받은 라이브러리를 오라클에 등록시킨다.
     
          C:\>loadjava -u sys/비밀번호@서비스명 jce*150.jar

3. 오라클에 sys (sysdba)로 접속하여 로드된 자바 클랙스 라이브러리의 상태를 확인하고 invalid상태의 오브젝트를 다시 컴파일 한다.

/* Formatted on 2014/04/01 09:55 (Formatter Plus v4.8.7) */
BEGIN    
    FOR rec IN (SELECT *                  
             FROM all_objects                 
             WHERE status <> 'VALID' 
             AND object_type = 'JAVA CLASS')    
     LOOP       
         BEGIN          
              EXECUTE IMMEDIATE    'ALTER JAVA CLASS SYS."'       || rec.object_name        || '" COMPILE';       
         EXCEPTION          
               WHEN OTHERS          THEN             
                    DBMS_OUTPUT.put_line (SQLERRM);       
         END;    
     END LOOP;
END;

4.  라이브러리를 이용하여 실제 데이터를 암호화, 복호화 하는 클랙스를 생성한다.

CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "DCrypto" AS
import java.security.MessageDigest;
import java.security.Security;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jcajce.provider.digest.BCMessageDigest;
import org.bouncycastle.jcajce.provider.digest.SHA256;

import sun.misc.BASE64Encoder;


import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

/*  참조 사이트 */
/* http://stackoverflow.com/questions/2208374/how-can-i-create-an-sha512-digest-string-in-java-using-bouncy-castle */
/* http://blog.daum.net/_blog/BlogTypeView.do?blogid=0ZDJJ&articleno=25&_bloghome_menu=recenttext */

public class DCrypto {

private static byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
private static byte[] IV = new byte[] { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
private static SecretKeySpec key = null;
private static String secKey = "SEED" ;  
private static String seedMethod = "SEED/CBC/PKCS5Padding";

/* 데이터 암호와 복호화를 위해  SEED 알고리즘을 사용한다. */
        /* srcStr 을 암호화 한다. */
public static String encrypt(String srcStr) throws Exception {
byte[] input = srcStr.getBytes(); 
Security.addProvider(new BouncyCastleProvider());

      key = new SecretKeySpec(keyBytes, secKey); 
IvParameterSpec ivSpec = new IvParameterSpec(IV); 
Cipher cipher = Cipher.getInstance(seedMethod, "BC"); 
cipher.init(Cipher.ENCRYPT_MODE, key,ivSpec); 
byte[] cipherText = cipher.doFinal(input); 


return String.valueOf(Hex.encodeHex(cipherText));

/* 암호화된 문자열을 복호화 한다. */
public static String decrypt(String encStr) throws Exception {

   byte[] input = (Hex.decodeHex(encStr.toCharArray()));
   Security.addProvider(new BouncyCastleProvider());
   key = new SecretKeySpec(keyBytes, secKey);
   IvParameterSpec ivSpec = new IvParameterSpec(IV); 
   Cipher cipher = Cipher.getInstance(seedMethod, "BC"); 
   cipher.init(Cipher.DECRYPT_MODE, key,ivSpec); 
   byte[] decryptedText = cipher.doFinal(input); 
   return new String(decryptedText);

/*  비밀번호 암호화를 위해   SHA-256, SHA-512 알고리즘을 이용한다. */
public static String decrytSHA256(String sourceStr) {
String result = "";
try {
Security.addProvider(new BouncyCastleProvider());
MessageDigest mda = MessageDigest.getInstance("SHA-256", "BC");
byte [] digesta = mda.digest(sourceStr.getBytes());

BASE64Encoder encoder = new BASE64Encoder();
result = encoder.encode(digesta);
} catch(Exception e) {
    result = ""; //e.getMessage();
}
return result;
}

public static String decryptSHA512(String sourceStr) {
String result = "";
try {
Security.addProvider(new BouncyCastleProvider());
MessageDigest mda = MessageDigest.getInstance("SHA-512", "BC");
byte [] digesta = mda.digest(sourceStr.getBytes());

BASE64Encoder encoder = new BASE64Encoder();
result = encoder.encode(digesta);
} catch(Exception e) {
    result = ""; //e.getMessage();
}
return result;
}
}

/


5. 해당 자바클랙스를 호출하여 쿼리문에서 사용할 수 있도록 패키지 또는 함수를 생성한다.

/* Formatted on 2014/04/01 10:12 (Formatter Plus v4.8.7) */
CREATE OR REPLACE PACKAGE cryptoAS    
FUNCTION decrypt (str_in VARCHAR2)       RETURN VARCHAR2;    
FUNCTION encrypt (str_in VARCHAR2)       RETURN VARCHAR2;    
FUNCTION encryptsha256 (str_in VARCHAR2)       RETURN VARCHAR2;    
FUNCTION encryptsha512 (str_in VARCHAR2)       RETURN VARCHAR2;
END;
/ 

CREATE OR REPLACE PACKAGE BODY cryptoAS    
    FUNCTION decrypt (str_in VARCHAR2)       RETURN VARCHAR2    
    AS       
        LANGUAGE JAVA       NAME 'DCrypto.decrypt(java.lang.String) return java.lang.String';    

    FUNCTION encrypt (str_in VARCHAR2)       RETURN VARCHAR2    
    AS       
        LANGUAGE JAVA       NAME 'DCrypto.encrypt(java.lang.String) return java.lang.String';    

    FUNCTION encryptsha256 (str_in VARCHAR2)       RETURN VARCHAR2    
    AS       
        LANGUAGE JAVA       NAME 'DCrypto.encryptSHA256(java.lang.String) return java.lang.String';    

    FUNCTION encryptsha512 (str_in VARCHAR2)       RETURN VARCHAR2    
    AS       
        LANGUAGE JAVA       NAME 'DCrypto.encryptSHA256(java.lang.String) return java.lang.String';
END;
/

6. sys유저로 생성된 객체를 다른 유저(스키마)에서 사용가능 하도록 시노님을 생성하고 권한을 부여한다.

CREATE PUBLIC SYNONYM CRYPTO FOR SYS.CRYPTO;

GRANT EXECUTE ON SYS.CRYPTO TO {데이터베이스유저1};

GRANT EXECUTE ON SYS.CRYPTO TO {데이터베이스유저2};

 7. 실제 사용 예제는 다음과 같다.

6번항목에서 권한을 부여한 사용자로 로그인 해서 아래의 쿼리로 테스트 한다. select CRYPTO.encrypt('test') from dual; 
select crypto.decrypt(crypto.encrypt('test')) from dual; 
select crypto.encryptSha256('010-5210-6848') from dual; 
select crypto.encryptSha512('010-5210-6848') from dual;

(실행결과)
——————————————————————
CRYPTO.ENCRYPT('TEST')                                                         
--------------------------------------------------------------------------------
UGOrhKh0YPlRJPX15DwIzQ==                                                       

1 row selected.

CRYPTO.DECRYPT(CRYPTO.ENCRYPT('TEST'))                                         
--------------------------------------------------------------------------------
test                                                                           

1 row selected.

CRYPTO.ENCRYPTSHA256('010-5210-6848')                                          
--------------------------------------------------------------------------------
AXLKeNy6+BmgogkI4blEcDlPIyKoPFWyNJtaK1l1wzE=                                   

1 row selected.

CRYPTO.ENCRYPTSHA512('010-5210-6848')                                          
--------------------------------------------------------------------------------
WPlGpM9F+E8mne0RiO3Da5mcb7gNHPUfNXzHQDQB6dQe/bNu3ZCPiHRpLrEipeWv/HsOnykdRvAh   
depIDUKUYg==                                                                   
                                                                               

1 row selected.