본문 바로가기
OraclE

오라클 암호화 복호화 초간단 예제(dbms_obfuscation_toolkit 편)

by 타마마임팩트_쫀 2009. 8. 28.

[출처] http://sinufam.tistory.com/22

데이터 암호화 기능 소개(8.1.6 new feature)
==========================================

개 요
=========
Oracle 8i Release2(8.1.6)에서는 데이터를 암호화하여 저장할 수 있는 향상된
기능(DES Encryption)을 제공한다
(Oracle 8i Release3(8.1.7)에서는 Triple DES Encryption)

즉 신용카드번호, 패스워드 등 보안이 필요한 데이터를 암호화된 형태로 저장하여
기존의 3rd Party Tool이나, Application Logic으로 구현하던 암호화 정책을
데이터베이스 차원에서 구현할 수 있도록 해준다.

DBMS_OBFUSCATION_TOOLKIT
========================
암호화 기능을 이용하려면 DBMS_OBFUSCATION_TOOLKIT을 이용해야 한다.

이 패키지는 4개의 프로시져로 이루어져 있다.
- VARCHAR2 타입을 Encrypt/Decrypt할 수 있는 2개의 프로시져
- RAW 타입을 Encrypt/Decrypt할 수 있는 2개의 프로시져
(다른 타입은 지원하지 않으므로 number인 경우는 to_char 이용)

DBMS_OBFUSCATION_TOOLKIT을 이용하기 위해서는 :
1) SYS 유저로
@$ORACLE_HOME/rdbms/admin/dbmsobtk.sql
@$ORACLE_HOME/rdbms/admin/prvtobtk.plb
2) grant execute on dbms_obfuscation_toolkit to public;


제 한 사 항
===========
1) DES(Data Encryption Standard) symmetric key algorithm 방식을 이용.
즉 암호화할 때 이용한 key를 분실했을 경우 데이터를 해독할 방법이 없다.

2) Encrypt하려는 data가 8 bytes 배수(8,16,... bytes)이어야 한다.

3) 미국무부의 암호화기술 수출제한조치에 의해 56-bit key를 사용.

4) 미국무부의 암호화기술 수출제한조치에 의해 한번 암호화된 데이터를
또다시 암호화할 수 없다.

*) 많은 테이블을 Encrypt/decrypt할 경우 CPU 사용량을 증가시킬 수 있다.


사 용 예
========
1) encrypt/decrypt에 이용할 FUNCTION을 만든다.
(만약 input string이 8 bytes 배수가 아니면 패딩을 한다)




암호화 복호화는 테스트 하고 설명하자면 끝도 없지만.
간단한 샘플 package 를 만들어서 직접 테스트 해 보면 그렇게 어렵지는 않다.

아래 관련자료 첨부하였으니
일단 한 번 수행 시켜서 수행해보고 이해해 보면 되겠다.

[by sinu] dbms_obfuscation_toolkit.txt 는 설명없이 스크립트만 들어 있으니 그냥 복사해서 붙이면 되고
(user 생성 및 clean 까지 되어 있다.)

[spool] dbms_obfuscation_toolkit.log 는 위 스크립트의 spool 결과이다.
수행여건이 안되거나 귀찮으신 분들을 위해;;



세세한 사항은 스크립트를 보면 되고 
중요한 부분만 간략하게 설명하도록 하겠다.

8i, 9i 와 같은 경우 dbms_obfuscation_toolkit 만 사용이 가능한데
아래처럼 실행 권한만 부여해 주면 된다.
 
grant execute on dbms_obfuscation_toolkit to sinu;

패키지 생성 소스를 살펴 보자

CREATE OR REPLACE PACKAGE pkg_obfus
IS
    FUNCTION encrypt (
        input_string        IN  VARCHAR2 ,
        key_data IN VARCHAR2 := '1122334455667788'
    ) RETURN RAW;
    
    FUNCTION decrypt (
        input_string        IN  VARCHAR2 ,
        key_data IN VARCHAR2 := '1122334455667788'
    ) RETURN VARCHAR2;

END pkg_obfus;
/

이 부분 부터가 패키지 바디 소스이다.

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

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

    BEGIN

-- 들어온 data 와 암호키를 각각 RAW 로 변환한다.
        input_string_raw := UTL_RAW.CAST_TO_RAW(input_string);
        key_data_raw  := UTL_RAW.CAST_TO_RAW(key_data);

-- DES 방식으로 암호화 한다.
        dbms_obfuscation_toolkit.DESEncrypt(
input => input_string_raw, 
key => key_data_raw, 
encrypted_data => encrypted_raw );
-- dbms_obfuscation_toolkit 를 수행하면 encrypted_raw 에 암호화된 data 가 raw 형태로 저장된다.

-- 암호화된 data 를 return (생각보다 간단하지 않은가?)
RETURN encrypted_raw;
    END encrypt;
    
    FUNCTION decrypt (input_string IN VARCHAR2 , key_data IN VARCHAR2 := '1122334455667788')
     RETURN VARCHAR2
    IS
        converted_string VARCHAR2(48);
        key_data_raw RAW(128);
        decrypted_raw VARCHAR2(2048);

    BEGIN
        key_data_raw  := UTL_RAW.CAST_TO_RAW(key_data);
        
-- 복호화 역시 간단하다. input_string 자체가 RAW 이므로 convert 하지 않아도 된다.
        dbms_obfuscation_toolkit.DESDecrypt(
input => input_string,
key => key_data_raw,
decrypted_data => decrypted_raw);

-- return 형태는 RAW 이므로 이를 다시 varchar2 로 변환하여 리턴한다.
        converted_string := UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw);
        RETURN converted_string;
    END decrypt ;

END pkg_obfus;
/

-- 암호화된 컬럼에 index 생성이 가능하다!!
create table card_info ( id number, card_number varchar(32) primary key) ; 

insert into card_info values ( 1 , pkg_obfus.encrypt('1234567812345678'));

-- 2nd argument 에 원하는 key 값을 넣을 수도 있다. 
insert into card_info values ( 2 , pkg_obfus.encrypt('1234567812345678', '0000111122223333'));
commit;

-- 같은 데이터 1234567812345678 을 넣었으나 key 값이 다르기 때문에 값이 전혀 다르다.
select * from card_info;
        ID CARD_NUMBER
---------- --------------------------------
         1 365C80EABBC8859E91C4BDE4B3C52A4B
         1 858B176DA8B125034356364E8179CD61

-- 2 번째 data 의 경우 key 값이 틀리기 때문에 복호화 되지 않고 에러를 뿌려준다.
select id, pkg_obfus.decrypt(card_number) card_number from card_info;

        ID CARD_NUMBER
---------- --------------------------------------------------
         1 1234567812345678
SP2-0784: Invalid or incomplete character beginning 0xF1 returned

-- 2 번째 row 의 key 값을 제대로 넣어주자 정상적으로 보인다.
select id, pkg_obfus.decrypt(card_number, '0000111122223333') card_number from card_info;

SP2-0784: Invalid or incomplete character beginning 0xEB returned
        ID CARD_NUMBER                     
---------- --------------------------------------------------
         2 1234567812345678                


-- [퀴즈] 특정 data 를 select 하려면 where 절에 어떤 형식으로 값을 주어야 할까?

1. select * from card_info where card_number = '1234567812345678';
2. select * from card_info where card_number = utl_raw.cast_to_raw('1234567812345678');

3. select * from card_info where card_number = '365C80EABBC8859E91C4BDE4B3C52A4B';
4. select * from card_info where card_number = pkg_obfus.encrypt('1234567812345678');

정답은 : 3 , 4 번 (드래그 하세요~)

소스는 길고 복잡해도 

포인트는 
dbms_obfuscation_toolkit.DESEncrypt
dbms_obfuscation_toolkit.DESDecrypt
요 2가지 이고 나머지는 그냥 varchar2 와 raw 의 converting 작업이다.

나머지 세세한 사항은 메뉴얼을 참고하자!






'OraclE' 카테고리의 다른 글

LOCAL_LISTENER and ORA-12545  (0) 2009.09.06
ASM 구성방법(ASM 설치)  (0) 2009.09.02
Oradim Utility  (0) 2009.08.07
Oracle10g R2부터 Group By절에 의한 자동정렬이 안되는 이유  (0) 2009.06.12
오라클 홈페이지 가입  (0) 2009.06.11