[출처]
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 작업이다.
나머지 세세한 사항은 메뉴얼을 참고하자!