ISMS 오라클 암호화키 관리

김철현·2021년 7월 6일
0

Encryption

목록 보기
5/5
post-thumbnail

ISMS AES-128 암호화키 관리
이전 글에선 WAS에서 jar모듈로 암호화키를 관리하는 포스팅을 올렸는데
오라클 스케줄러 내 호출하는 프로시저에서 암/복호화를 할 시 관리 방법에 대해 포스팅한다

📝 설계

  1. 암호화키를 서버 내 별도파일에 암호화하여 저장한다
  2. 오라클에서 파일을 읽어 암호화키를 가져온다
  3. 패키지함수를 사용하여 암호화키를 복호화하여 암호화키를 가져온다
  4. 암호화키 관리자 외 소스를 볼 수 없도록 패키지를 암호화한다
  5. 해당 함수를 호출하는 모든 프로시저를 암호화한다

📝 암호화키 저장

서버 내 암호화키를 암호화하여 파일에 저장
오라클을 설치한 계정으로 폴더를 만들거나 root로 생성 후 오라클 계정에 폴더 권한을
부여해 접근할 수 있도록 설정

디렉토리 생성 및 파일 생성

mkdir /home/oracle/enc_key

vi /home/oracle/enc_key/enc_key.txt
ED6CF66DAF90E7D9C6935E1B47643210791603D8B6745F0E31B2C14CFA31A3C7 입력

cat /home/oracle/enc_key/enc_key.txt
ED6CF66DAF90E7D9C6935E1B47643210791603D8B6745F0E31B2C14CFA31A3C7

📝 파일 읽기

UTL_FILE

오라클 UTL_FILE
UTL_FILE은 운영체제에서 관리하는 파일에 접근하기 위한 함수와 프로시저를 제공하는 패키지다
파일의 경로는 DIRECTORY로 접근할 수 있어 접근이 가능한지 확인한다

오라클 디렉토리 생성 및 조회

CREATE DIRECTORY ENC_KEY AS '/home/oracle/enc_key'
SELECT * FROM ALL_DIRECTORIES

생성한 파일에 접근 가능한지 확인.

DECLARE
  FHANDLE UTL_FILE.FILE_TYPE;
  FBUFFER VARCHAR2(64);
BEGIN
  FHANDLE := UTL_FILE.FOPEN('ENC_KEY', 'enc_key.txt', 'R');
  UTL_FILE.GET_LINE(FHANDLE, FBUFFER);
  DBMS_OUTPUT.PUT_LINE(FBUFFER);
  UTL_FILE.FCLOSE(FHANDLE);
END;

실행결과: ED6CF66DAF90E7D9C6935E1B47643210791603D8B6745F0E31B2C14CFA31A3C7

✍ 패키지 생성

암호화키를 가져오는 ENCKEY 패키지 GET_ENC_KEY 함수를 생성

패키지 선언부

CREATE OR REPLACE PACKAGE TEST.ENCKEY
IS
	FUNCTION GET_ENC_KEY RETURN VARCHAR2;	
END ENCKEY;

패키지 구현부

CREATE OR REPLACE PACKAGE BODY TEST.ENCKEY
IS
	FUNCTION GET_ENC_KEY RETURN VARCHAR2
	IS
		FHANDLE UTL_FILE.FILE_TYPE;
		FBUFFER VARCHAR2(64);
		INPUT_STRING VARCHAR2(64);
		KEY_RAW RAW(16) := UTL_RAW.CAST_TO_RAW('test1234test1234');
		OUTPUT_RAW RAW(1024);
		V_OUT_STRING VARCHAR2(1024);
		AES_CBC_PKCS5 CONSTANT PLS_INTEGER := 
        DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
	BEGIN
		--CREATE DIRECTORY ENC_KEY AS '/home/oracle/enc_key'
		--SELECT * FROM ALL_DIRECTORIES
		FHANDLE := UTL_FILE.FOPEN('ENC_KEY', 'enc_key.txt', 'R');
		UTL_FILE.GET_LINE(FHANDLE, FBUFFER, 64);
		INPUT_STRING := FBUFFER;
		UTL_FILE.FCLOSE(FHANDLE);
		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);	
		V_OUT_STRING := UTL_I18N.RAW_TO_CHAR(OUTPUT_RAW, 'AL32UTF8');
	RETURN V_OUT_STRING;
	END GET_ENC_KEY;	
END ENCKEY;	

패키지 함수 생성 후 잘 나오는지 확인

SELECT ENCKEY.GET_ENC_KEY FROM dual

✍ 패키지 암호화

DBMS_DDL

오라클 DBMS_DDL
DBMS_DDL은 CREATE OR REPLACE PROCEDURE, PACKAGE로 시작하는 DDL 구문에 대한
WRAPPING 기능 외 기타 DDL 관련 기능을 제공하는 패키지이며
CREATE_WRAPPED 프로시저를 사용하면 패키지 소스를 숨기는 것과 동시에 컴파일도 수행한다

생성한 패키지 내용을 보면 GET_ENC_KEY 함수를 호출하면 암호화키를 얻을 수 있는 것을
알 수 있고 암호화키를 암/복호화하는 암호화키를 얻을 수 있기 때문에
선언부, 구현부 소스 모두 암호화 하여 평문의 소스는 별도 관리한다

패키지 선언부 암호화

varchar2는 최대길이가 4000byte기 때문에 긴 내용을 암호화 할 땐 CLOB 타입을 사용
(CLOB 최대길이 4GB)

DECLARE
  src CLOB;
BEGIN
  src := 
'
CREATE OR REPLACE PACKAGE TEST.ENCKEY
IS
	FUNCTION GET_ENC_KEY RETURN VARCHAR2;
END ENCKEY;
';
DBMS_DDL.CREATE_WRAPPED (src);

EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END ;

패키지 구현부 암호화

DECLARE
  src CLOB;
BEGIN
  src := 
'
CREATE OR REPLACE PACKAGE BODY TEST.ENCKEY
IS
	FUNCTION GET_ENC_KEY RETURN VARCHAR2
	IS
		FHANDLE UTL_FILE.FILE_TYPE;
		FBUFFER VARCHAR2(64);
		INPUT_STRING VARCHAR2(64);
		KEY_RAW RAW(16) := UTL_RAW.CAST_TO_RAW(''test1234test1234'');
		OUTPUT_RAW RAW(1024);
		V_OUT_STRING VARCHAR2(1024);
		AES_CBC_PKCS5 CONSTANT PLS_INTEGER := 
        DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
	BEGIN
		--CREATE DIRECTORY ENC_KEY AS ''/home/oracle/enc_key''
		--SELECT * FROM ALL_DIRECTORIES
		FHANDLE := UTL_FILE.FOPEN(''ENC_KEY'', ''enc_key.txt'', ''R'');
		UTL_FILE.GET_LINE(FHANDLE, FBUFFER, 64);
		INPUT_STRING := FBUFFER;
		UTL_FILE.FCLOSE(FHANDLE);
		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);	
		V_OUT_STRING := UTL_I18N.RAW_TO_CHAR(OUTPUT_RAW, ''AL32UTF8'');
	RETURN V_OUT_STRING;
	END GET_ENC_KEY;	
END ENCKEY;	
';
DBMS_DDL.CREATE_WRAPPED (src);

EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END ;

암호화된 패키지 확인

CREATE OR REPLACE PACKAGE BODY      TEST.ENCKEY wrapped 
a000000
369
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
b
346 258
d7fOkKhxMcBsoykWCbGefn3PBr0wg3lezPYFfC8ZCk7Vud6fEXwuYY1LJTdWT3bzLmXxaPdJ
f/K0ymMojCgFP3O5fsYK6+Z2Gvi5vHL+Vb6UwJarRpc9W2fV/jBUfUuFwxcBd//m1n/MevOm
HAvBYmiZlr8VIG+IF8knSX55L0UR8SU5DPkMCFAGYoxcsI6SJk1TOlNdU2F5H17jhwWLlFrg
+m0gZ64tvJMVwZhBkOJjjqjofc5xXbGwuyQ/+RDkgdLOuPK70LA0ZJ9Mkbn0jyOCSxlJ/kBd
Npl0oStlDRKIIjf136I476AbFHnv33c27YBMEGMhqhGM1fofIhTlcSBhuCod9Ey6GzTjxFEc
FFoDFWC68Rw/F+/GSFuWTG1hhca9XdWF0K4oKfXkXiK1P4sKLCNBnjCHYLpWYGGUX7ZUr7r/
tzzjclSJIdFZdoRYrJNjy3DaC8q5yLpXllvGV6R5sqNMX4YVnav4hDWhk280RpiWgvBcKFAb
f3z9cqml3NNlSNmb35h2m30ahyB5oYg0eHrSBrXV99YVz7T1zHkS73LV+awCUWhHbSg3Rldl
z9H1Qv4o30538w==

이런 식으로 암호화 되어 저장된다
함수 호출 시 잘 나오는지 확인
crypto.encrypt는 아래 포스팅에서 작성한 함수다
(Oracle DBMS_CRYPTO)

SELECT crypto.encrypt('개인정보', ENCKEY.GET_ENC_KEY) FROM dual

💡 마치며

ENCKEY.GET_ENC_KEY를 호출하면 암호화키를 확인할 수 있기 때문에 해당 함수를 호출하는
모든 프로시저를 암호화(wrap)해야 한다고 하여 위와 마찬가지로 CLOB타입으로 전부 처리했다

profile
리팩토링만이 살 길이다

0개의 댓글