프린트 하기

OS환경 : Oracle Linux 6.8 (64bit)


DB 환경 : Oracle Database 11.2.0.4


방법 : DBMS_OBFUSCATION_TOOLKIT 암호화 방법

이 패키지는 VARCHAR2 타입을 Encrypt/Decrypt할 수 있는 2개의 프로시져와 RAW 타입을 Encrypt/Decrypt할 수 있는 2개의 프로시져 이렇게 4개의 프로시져로 이루어져 있음

DBMS_OBFUSCATION_TOOLKIT을 이용하기 위해서는 SYS 사용자에서 아래의 스크립트를 실행 시켜야 함



스크립트 실행 및 권한 부여

1
2
3
SQL> @$ORACLE_HOME/rdbms/admin/dbmsobtk.sql
SQL> @$ORACLE_HOME/rdbms/admin/prvtobtk.plb
SQL> GRANT execute ON dbms_obfuscation_toolkit TO public;



패키지 생성

1
2
3
4
5
6
SQL> 
CREATE OR REPLACE PACKAGE CryptIT AS 
FUNCTION encrypt( Str VARCHAR2, hash VARCHAR2 ) RETURN VARCHAR2;
FUNCTION decrypt( xCrypt VARCHAR2, hash VARCHAR2 ) RETURN VARCHAR2;
END CryptIT;
/



패키지 바디 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
SQL> CREATE OR REPLACE PACKAGE BODY CryptIT AS 
        crypted_string VARCHAR2(2000);
 
        FUNCTION encrypt( Str VARCHAR2,  
                     hash VARCHAR2 ) RETURN VARCHAR2 AS
        pieces_of_eight INTEGER := ((FLOOR(LENGTH(Str)/8 + .9)) * 8);
 
      BEGIN
 
        DBMS_OBFUSCATION_TOOLKIT.DESENCRYPT(
            input_string     => RPAD( Str, pieces_of_eight ),
            key_string       => RPAD(hash,8,'#'), 
            encrypted_string => crypted_string 
        );
            
        RETURN crypted_string;
      END;
 
      FUNCTION decrypt( xCrypt VARCHAR2,
                     hash VARCHAR2 ) RETURN VARCHAR2 AS 
      BEGIN
        DBMS_OBFUSCATION_TOOLKIT.DESDECRYPT(
           input_string     => xCrypt, 
           key_string       => RPAD(hash,8,'#'), 
           decrypted_string => crypted_string 
        );
           
        RETURN trim(crypted_string);
     END;
  END CryptIT;
  /



암호화 테스트

테스트 테이블 생성 및 데이터 삽입

1
2
3
4
5
6
SQL> CREATE TABLE encrypt_table( id number, passwd VARCHAR(20) );
SQL> INSERT INTO encrypt_table VALUES1, CryptIT.encrypt('1234''storm'));
SQL> INSERT INTO encrypt_table VALUES2, CryptIT.encrypt('5678''oramaster'));
SQL> INSERT INTO encrypt_table VALUES3, CryptIT.encrypt('5678''oramaster'));
SQL> INSERT INTO encrypt_table VALUES4, CryptIT.encrypt('5678''oracle'));
SQL> COMMIT;

CryptIT.encrypt(비밀번호, 키값)



암호화 데이터 조회

1
2
3
SQL> SELECT id, passwd FROM encrypt_table WHERE passwd = '1234';
 
no rows selected

Decrypt하지 않으면 암호화된 데이터와 비교되서 결과값이 출력되지 않음



Encrypt 된 값 조회

1
2
3
4
5
6
7
8
9
10
SQL> 
COL passwd FORMAT a60
SELECT id, DUMP(passwd) passwd FROM encrypt_table;
 
    ID PASSWD
---------- ------------------------------------------------------------
     1 Typ=1 Len=821,175,48,36,49,172,203,95
     2 Typ=1 Len=831,183,20,76,238,89,44,236
     3 Typ=1 Len=831,183,20,76,238,89,44,236
     4 Typ=1 Len=8148,30,122,231,240,179,162,113

ID 2번, 3번은 pw와 key가 모두 같아서 암호화된 pw도 동일하게 저장됨

하지만 ID 4번은 pw는 ID 2번, 3번과 같지만 key 가 다르기 때문에 암호화되는 pw값이 다름



Encrypt할 때 사용한 Key로만 Decrypt할 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
SQL> 
SELECT id, CryptIT.decrypt(passwd,'storm') passwd
FROM encrypt_table 
WHERE CryptIT.decrypt(passwd,'storm'= '1234';
 
  ID   PASSWD
------ ----
    1  1234
 
SQL> 
SELECT id, CryptIT.decrypt(passwd,'oramaster') passwd
FROM encrypt_table 
WHERE CryptIT.decrypt(passwd,'oramaster'= '5678';
 
  ID   PASSWD
------ ----
    2  5678
    3  5678
 
SQL> 
SELECT id, CryptIT.decrypt(passwd,'oracle') passwd
FROM encrypt_table 
WHERE CryptIT.decrypt(passwd,'oracle'= '5678';
 
  ID   PASSWD
------ ----
    4  5678



ID 4번의 pw와 key 변경

1
2
3
4
SQL> update encrypt_table set passwd=cryptit.encrypt('1234','storm'where id=4;
 
1 row updated.
SQL> commit;



Decrypt 된 값 확인

1
2
3
4
5
6
7
8
9
SQL> 
SELECT id, CryptIT.decrypt(passwd,'storm') passwd
FROM encrypt_table 
WHERE CryptIT.decrypt(passwd,'storm'= '1234';
 
  ID   PASSWD
------ ----
    1  1234
    4  1234



Encrypt 된 값 조회

1
2
3
4
5
6
7
8
9
10
SQL> 
COL passwd FORMAT a60
SELECT id, DUMP(passwd) passwd FROM encrypt_table;
 
    ID PASSWD
---------- ------------------------------------------------------------
     1 Typ=1 Len=821,175,48,36,49,172,203,95
     2 Typ=1 Len=831,183,20,76,238,89,44,236
     3 Typ=1 Len=831,183,20,76,238,89,44,236
     4 Typ=1 Len=821,175,48,36,49,172,203,95

ID 2번, 3번은 pw와 key가 모두 같아서 암호화된 pw도 동일하게 저장됨

ID 1번, 4번도 pw와 key가 모두 같아서 암호화된 pw도 동일하게 저장됨



관련 에러 메세지

ORA-28231 "Invalid input to Obfuscation toolkit" - input data, key값이 NULL일 경우 발생

ORA-28232 "Invalid input size for Obfuscation toolkit" - input data가 8 bytes 배수가 아닐 경우 발생

ORA-28233 "Double encryption not supported by DESEncrypt in Obfuscation toolkit" - encrypt data를 다시 encrypt경우 발생(데이터를 이중 암호화하려고 하면 발생)

ORA-28234 "Key length too short." - 키 길이가 누락되었거나 8 바이트 미만이면 프로 시저에서 오류가 발생



참조 : http://www.gurubee.net/lecture/1200

https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_obtool.htm#i1003970