오라클 DBMS_CRYPTO

김철현·2021년 5월 26일
2

Encryption

목록 보기
2/5
post-thumbnail

앞 포스팅에서 KTC보안인증 및 클라이언트 프로그램 무결성 검사를 위한 해시값 비교 글에서
KTC보안인증에 대한 내용이 포함되어 있어 생략하고 오라클에서 지원하는 패키지를 사용하여
개인정보(민감데이터)를 암호화 한 내용이다

KTC보안인증 C# SHA-1 해시값 비교

📝 DBMS_CRYPTO

DBMS_CRYPTO는 저장된 데이터를 암호화하고 해독하는 인터페이스를 제공하며 네트워크 통신을 실행하는 PL / SQL 프로그램과 함께 사용할 수 있다. AES (Advanced Encryption Standard) 암호화 알고리즘을 포함하여 여러 산업 표준 암호화 및 해싱 알고리즘을 지원한다

단방향 암호화인 해시암호화와 달리 데이터 저장은 암호화하여 저장하고 사용자에게 보여줄 땐 복호화하여 출력할 수 있는 양방향 암호방식이고 본문에선 AES-128 방식을 사용하여 128bit(16byte) 대칭키(비밀키)를 사용한다

✍ DBMS_CRYPTO 패키지 설치

  1. 오라클 계정에서 sysba 권한으로 로그인

    sqlplus / as sysdba

  2. CRYPTO 패키지 추가

    @$ORACLE_HOME/rdbms/admin/dbmsobtk.sql

    @$ORACLE_HOME/rdbms/admin/prvtobtk.plb

  3. 패키지 사용권한 추가

    grant execute on dbms_crypto to public;
    grant execute on dbms_obfuscation_toolkit to public;

📝 패키지 사용 전

DBMS_CRYPTO 오라클 도큐먼트

  • 암호화 알고리즘
알고리즘설명
DES64 bit의 블록 단위로 나누어 각각을 56 bit의 키를 사용하는 대칭키 알고리즘.
보안성이 보장되지 않아 사용빈도 줄어드는 추세다
3DESDES 알고리즘을 2~3번 반복하여 적용한다. 각각 112(562)bit와 168(563)bit 키를 사용하는 대칭키 알고리즘이며
타 대칭키 알고리즘에 비해 암/복호화를 하는 시간이 많이 필요함
AES128 bit의 블록 단위로 나누어 각각을 128, 192, 혹은 256 bit의 키를 사 용하는 알고리즘
DES 방식보다 강력한 알고리즘으로 설계되아 암호화 표준으로 자리 잡음
  • 체인방식
체인방식설명
ECB
(Electronic Codebook)
각 원본 데이터 블록들 각각 별개로 암호화
CBC
(Cipher Block Chaining)
현재 블록이 바로 앞에 암호화된 블록의 데이터와 XOR 연산 후 암호화
(ECB 방식처럼 동일한 원본이 있을 경우 동일 암호문 생성 방지)
CFB
(Cipher Feedback)
비트단위로 암호화하면서 시프트 시키는 방식으로 스트림 암호화 방식에 가깝다
블록크기보다 작은 단위의 데이터 암호화 가능
OFB
(Output Feedback)
블록 암호가 동기화된 스트림 암호처럼 동작하게 함
CFB와 유사하지만 다음 블록을 위한 키배열 조합에 있어서 현재 블록의 암호문이 영향을 끼치지 않는 장점
  • 패딩방식
패딩방식설명
PKCS5PKCS #5(Password-Based Cryptography Standard) 표준 방식
NONE패딩 미사용. 데이터가 단위블록의 크기(128bit)의 배수가 아니면 암호화 불가하므로 데이터의 크기를 확인해야 함
ZERO마지막 블록의 남는 바이트들을 0으로 채움.문자열과 같이 0의 값으로 끝을 체크하는 데이터에만 사용해야 함
  • 함수 원형
DBMS_CRYPTO.ENCRYPT
(
	src IN RAW,			--암호화할 데이터
	cipher_type IN PLS_INTEGER,	--사용할 암호알고리즘, 체인, 패딩 기법
	key IN RAW,		        --암호화키
	init_vector IN RAW DEFAULT NULL --초기화 벡터 NULL or 0
)
RETURN RAW;

DBMS_CRYPTO.DECRYPT(
   src IN RAW,				--복호화할 데이터
   typ IN PLS_INTEGER,
   key IN RAW,
   iv  IN RAW DEFAULT NULL
)
RETURN RAW;

✍ DBMS_CRYPTO를 사용할 패키지 생성 및 함수 사용

CREATE OR REPLACE PACKAGE TEST.CRYPTO
IS
    FUNCTION ENCRYPT (input_string IN VARCHAR2
                    , key_data IN VARCHAR2 := 'test1234test1234') 
    RETURN RAW;
    FUNCTION DECRYPT (input_string IN VARCHAR2
                    , key_data IN VARCHAR2 := 'test1234test1234')
    RETURN VARCHAR2;
END CRYPTO;
CREATE OR REPLACE PACKAGE BODY TEST.CRYPTO
IS
    SQLERRMSG   VARCHAR2(255);
    SQLERRCDE   NUMBER;
     
    --암호화 함수
    FUNCTION encrypt (input_string IN VARCHAR2
                    , key_data IN VARCHAR2 := 'test1234test1234') 
     RETURN RAW
    IS
        input_raw RAW(1024);
        --평문 암호화키 RAW 타입으로 변환
        key_raw RAW(16) := UTL_RAW.CAST_TO_RAW(key_data);
        v_out_raw RAW(1024);
        --AES 알고리즘, CBC 체인, PKCS5 패딩방식 사용
        AES_CBC_PKCS5 CONSTANT PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_AES128 
                                            + DBMS_CRYPTO.CHAIN_CBC 
                                            + DBMS_CRYPTO.PAD_PKCS5;
    BEGIN
        IF input_string IS NULL THEN
         RETURN NULL;
        end IF;
        
        --암호화 할 문자열 RAW 타입으로 변환
        input_raw := UTL_I18N.STRING_TO_RAW(input_string, 'AL32UTF8');
        v_out_raw := DBMS_CRYPTO.ENCRYPT(
                src => input_raw,       
                typ => AES_CBC_PKCS5,   
                key => key_raw);        
    --암호화된 RAW 타입 데이터 리턴
    RETURN v_out_raw;
    END encrypt;
    
    --복호화 함수
    FUNCTION decrypt (input_string IN VARCHAR2
                    , key_data IN VARCHAR2 := 'test1234test1234') 
     RETURN VARCHAR2
    IS
        --평문 암호화키 RAW 타입으로 변환
        key_raw RAW(16) := UTL_RAW.CAST_TO_RAW(key_data);
        output_raw RAW(1024);
        v_out_string VARCHAR2(1024);
        --AES 알고리즘, CBC 체인, PKCS5 패딩방식 사용
        AES_CBC_PKCS5 CONSTANT PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_AES128 
  					    + DBMS_CRYPTO.CHAIN_CBC
  					    + DBMS_CRYPTO.PAD_PKCS5;

    BEGIN
        IF input_string IS NULL THEN
         RETURN NULL;
        end IF;
    
        output_raw := DBMS_CRYPTO.DECRYPT(
                src => input_string,
                typ => AES_CBC_PKCS5,
                key => key_raw);
        --복호화 한 RAW 데이터 UTF-8 형식의 문자열로 변환
        v_out_string := UTL_I18N.RAW_TO_CHAR(output_raw, 'AL32UTF8');
    --복호화된 문자열 타입 데이터 리턴
    RETURN v_out_string;
    END decrypt ;
END CRYPTO;

💡 사용하는 패키지, 함수, 데이터타입 짚고 넘어가기

  • RAW : 2진수 binary data 또는 16진수 byte string을 저장 (maximum length: 2000byte)

  • PLS_INTEGER : INTERGER 또는 NUMBER 타입은 라이브러리를 이용하여 수치 연산을 하는 반면
    PLS_INTEGER는 실제 기계적인 연산을 수행하기 때문에 처리속도에서 유리하기 때문에 사용

  • UTL_RAW: RAW 타입의 데이터 관련 함수 제공 패키지

  • UTL_RAW.CAST_TO_RAW: STRING을 RAW로 변환

  • UTL_I18N: 국가, 언어들 간의 다양한 호환 기능 제공 패키지

  • UTL_I18N.STRING_TO_RAW: STRING을 RAW로 변환

  • UTF8과 AL32UTF8 비교

캐릭터셋유니코드 버전유니코드 인코딩가변길이보충,보조 문자열 지원오라클 버전
AL32UTF83.0~3.1UTF-84byteU+10000~U+10FFFF 코드 할당
(이모지, 더 많은 한자 사용 가능)
9i 이후
UTF82.1~3.0UTF-83byteX8~9l

제 오라클 환경은 기본 캐릭터셋이 AL32UTF8 이라 두 함수의 결과값이 같게 나왔습니다.

--현재 데이터베이스 캐릭터셋
--결과: NLS_CHARACTERSET	AL32UTF8
SELECT * 
FROM NLS_DATABASE_PARAMETERS
WHERE PARAMETER = 'NLS_CHARACTERSET'

--결과: 5445535431323334
SELECT UTL_RAW.CAST_TO_RAW('TEST1234') 
FROM DUAL

--결과: 5445535431323334
SELECT UTL_I18N.STRING_TO_RAW('TEST1234', 'AL32UTF8') 
FROM DUAL

✍ 작성한 함수 사용

--암호화
SELECT CRYPTO.ENCRYPT('01012345678') 
FROM DUAL

--복호화
SELECT CRYPTO.DECRYPT('357788CC5A3C8551550D62EA308CCF30') 
FROM DUAL
profile
리팩토링만이 살 길이다

0개의 댓글