보안에도 무척이나 취약하다.
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