앞 포스팅에서 KTC보안인증 및 클라이언트 프로그램 무결성 검사를 위한 해시값 비교 글에서
KTC보안인증에 대한 내용이 포함되어 있어 생략하고 오라클에서 지원하는 패키지를 사용하여
개인정보(민감데이터)를 암호화 한 내용이다
DBMS_CRYPTO는 저장된 데이터를 암호화하고 해독하는 인터페이스를 제공하며 네트워크 통신을 실행하는 PL / SQL 프로그램과 함께 사용할 수 있다. AES (Advanced Encryption Standard) 암호화 알고리즘을 포함하여 여러 산업 표준 암호화 및 해싱 알고리즘을 지원한다
단방향 암호화인 해시암호화와 달리 데이터 저장은 암호화하여 저장하고 사용자에게 보여줄 땐 복호화하여 출력할 수 있는 양방향 암호방식이고 본문에선 AES-128 방식을 사용하여 128bit(16byte) 대칭키(비밀키)를 사용한다
오라클 계정에서 sysba 권한으로 로그인
sqlplus / as sysdba
CRYPTO 패키지 추가
@$ORACLE_HOME/rdbms/admin/dbmsobtk.sql
@$ORACLE_HOME/rdbms/admin/prvtobtk.plb
패키지 사용권한 추가
grant execute on dbms_crypto to public;
grant execute on dbms_obfuscation_toolkit to public;
알고리즘 | 설명 |
---|---|
DES | 64 bit의 블록 단위로 나누어 각각을 56 bit의 키를 사용하는 대칭키 알고리즘. 보안성이 보장되지 않아 사용빈도 줄어드는 추세다 |
3DES | DES 알고리즘을 2~3번 반복하여 적용한다. 각각 112(562)bit와 168(563)bit 키를 사용하는 대칭키 알고리즘이며 타 대칭키 알고리즘에 비해 암/복호화를 하는 시간이 많이 필요함 |
AES | 128 bit의 블록 단위로 나누어 각각을 128, 192, 혹은 256 bit의 키를 사 용하는 알고리즘 DES 방식보다 강력한 알고리즘으로 설계되아 암호화 표준으로 자리 잡음 |
체인방식 | 설명 |
---|---|
ECB (Electronic Codebook) | 각 원본 데이터 블록들 각각 별개로 암호화 |
CBC (Cipher Block Chaining) | 현재 블록이 바로 앞에 암호화된 블록의 데이터와 XOR 연산 후 암호화 (ECB 방식처럼 동일한 원본이 있을 경우 동일 암호문 생성 방지) |
CFB (Cipher Feedback) | 비트단위로 암호화하면서 시프트 시키는 방식으로 스트림 암호화 방식에 가깝다 블록크기보다 작은 단위의 데이터 암호화 가능 |
OFB (Output Feedback) | 블록 암호가 동기화된 스트림 암호처럼 동작하게 함 CFB와 유사하지만 다음 블록을 위한 키배열 조합에 있어서 현재 블록의 암호문이 영향을 끼치지 않는 장점 |
패딩방식 | 설명 |
---|---|
PKCS5 | PKCS #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;
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 비교
캐릭터셋 | 유니코드 버전 | 유니코드 인코딩 | 가변길이 | 보충,보조 문자열 지원 | 오라클 버전 |
---|---|---|---|---|---|
AL32UTF8 | 3.0~3.1 | UTF-8 | 4byte | U+10000~U+10FFFF 코드 할당 (이모지, 더 많은 한자 사용 가능) | 9i 이후 |
UTF8 | 2.1~3.0 | UTF-8 | 3byte | X | 8~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