상세 컨텐츠

본문 제목

Oracle 암호화 / 복호화

DataBase/Oracle

by 탑~! 2015. 1. 22. 17:40

본문

dbms_obfuscation_toolkit 의 경우 지원되는 암호화 알고리즘이 너무 적고
보안에도 무척이나 취약하다.

10g 부터는 dbms_crypto 가 새로 지원이 되면서 AES 와 같은 알고리즘도 지원이 되고
lob data 도 지원하니 활용도가 무척 높아 졌다고 볼 수 있겠다.

-- dbms_crypto 에 대한 실행 권한만 부여하면 권한은 끝!
grant execute on DBMS_CRYPTO to sinu;

-- package 껍데기
CREATE OR REPLACE PACKAGE pkg_crypto
IS
    FUNCTION encrypt (
        input_string        IN  VARCHAR2 ,
        key_data IN VARCHAR2 := '12345678'
    ) RETURN RAW;
    
    FUNCTION decrypt (
        input_string        IN  VARCHAR2 ,
        key_data IN VARCHAR2 := '12345678'
    ) RETURN VARCHAR2;

END pkg_crypto;
/

-- package body 를 살펴보자
CREATE OR REPLACE PACKAGE BODY pkg_crypto
IS
-- 에러 발생시에 error code 와 message 를 받기 위한 변수 지정.
    SQLERRMSG   VARCHAR2(255);
    SQLERRCDE   NUMBER;

-- 암호화 함수 선언 key_data 는 입력하지 않을 시에 default 로 12345678 로 지정됨.
    FUNCTION encrypt (input_string IN VARCHAR2 , key_data IN VARCHAR2 := '12345678') 
     RETURN RAW
    IS
    
        key_data_raw        RAW(64);
        converted_raw       RAW(64);
        encrypted_raw       RAW(64);

    BEGIN

-- 들어온 data 와 암호키를 각각 RAW 로 변환한다.
        converted_raw := UTL_I18N.STRING_TO_RAW(input_string, 'AL32UTF8');
        key_data_raw     := UTL_I18N.STRING_TO_RAW(key_data, 'AL32UTF8');

-- DBMS_CRYPTO.ENCRYPT 로 암호화 하여 encrypted_raw 에 저장.
        encrypted_raw := 
             DBMS_CRYPTO.ENCRYPT(
                 src => converted_raw ,
-- typ 부분만 변경하면 원하는 알고리즘을 사용할 수 있다. 
--단, key value bype 가 다 다르니 확인해야 한다.
                 typ => DBMS_CRYPTO.DES_CBC_PKCS5 ,
                 key => key_data_raw ,
                 iv =>  NULL);
        
        RETURN encrypted_raw;
    END encrypt;

    FUNCTION decrypt (input_string IN VARCHAR2 , key_data IN VARCHAR2 := '12345678') 
     RETURN VARCHAR2
    IS
        converted_string    VARCHAR2(64);
        key_data_raw        RAW(64);
        decrypted_raw    VARCHAR2(64);

    BEGIN

        key_data_raw     := UTL_I18N.STRING_TO_RAW(key_data, 'AL32UTF8');
        
        decrypted_raw := 
            DBMS_CRYPTO.DECRYPT(
                 src => input_string ,
                 typ => DBMS_CRYPTO.DES_CBC_PKCS5 ,
                 key => key_data_raw ,
                 iv =>  NULL);

-- DBMS_CRYPTO.DECRYPT 수행 결과 나온 복호화된 raw data 를 varchar2 로 변환하면 끝!
        converted_string := UTL_I18N.RAW_TO_CHAR(decrypted_raw, 'AL32UTF8');

        RETURN converted_string;
    END decrypt ;
END pkg_crypto;
/


create table card_info ( id number, card_number varchar2(64) ) ;

-- 8자리 16자리 data 를 넣어보자.
insert into card_info values ( 1 , pkg_crypto.encrypt('1234567812345678')) ;
insert into card_info values ( 2 , pkg_crypto.encrypt('12345678')) ;
commit;

-- 암호화 되어 return 되는 bytes 가 다르다!
select * from card_info ;
        ID CARD_NUMBER                                     
---------- ----------------------------------------------------------------
         1 96D0028878D58C89D73FBE0238428B0A3D440C49910337FB
         2 96D0028878D58C898E250D5F4C76644B                

-- 복호화 해보니 정상적으로 잘 보인다.
select id , pkg_crypto.decrypt(card_number) card_number
from card_info;

        ID CARD_NUMBER                                     
---------- ----------------------------------------------------------------
         1 1234567812345678                                
         2 12345678                                        

-- key value 를 00000000 으로 바꾸어 보자
insert into card_info values ( 3 , pkg_crypto.encrypt('1234567812345678','00000000')) ;

-- 데이터는 id=1 과 같은데 key 가 다르므로 암호화된 값이 다름을 알 수 있다.
select * from card_info where id = 3;
        ID CARD_NUMBER                                     
---------- ----------------------------------------------------------------
         3 858B176DA8B125034356364E8179CD61040EE2CAC3041331

-- 복호화 할 때는 반드시 암호화 시 사용했던 key value 가 필요하다.
select id , pkg_crypto.decrypt(card_number,'00000000') card_number from card_info where id = 3  ;

        ID CARD_NUMBER                                     
---------- ----------------------------------------------------------------
         3 1234567812345678                                


포인트는 
DBMS_CRYPTO.ENCRYPT
DBMS_CRYPTO.DECRYPT
요 2가지 이고 나머지는 그냥 varchar2 와 raw 의 converting 작업이다.


출처: http://flutejava.tistory.com/128


관련글 더보기