더북(TheBook)

암호화 실습

지금까지 살펴 본 DBMS_CRYPTO 패키지를 사용해 문자열 데이터를 암호화하고 이를 다시 복호화 하는 익명 블록을 만들어 보자.

입력

    DECLARE
      input_string  VARCHAR2 (200) := 'The Oracle';  -- 암호화할 VARCHAR2 데이터
      output_string VARCHAR2 (200); -- 복호화된 VARCHAR2 데이터

      encrypted_raw RAW (2000); -- 암호화된 데이터
      decrypted_raw RAW (2000); -- 복호화할 데이터

      num_key_bytes NUMBER := 256/8; -- 암호화 키를 만들 길이 (256 비트, 32 바이트)
      key_bytes_raw RAW (32);        -- 암호화 키

      -- 암호화 슈트
      encryption_type PLS_INTEGER;

    BEGIN
     -- 암호화 슈트 설정
     encryption_type := DBMS_CRYPTO.ENCRYPT_AES256 + -- 256비트 키를 사용한 AES 암호화
                        DBMS_CRYPTO.CHAIN_CBC +      -- CBC 모드
                        DBMS_CRYPTO.PAD_PKCS5;       -- PKCS5로 이루어진 패딩

       DBMS_OUTPUT.PUT_LINE ('원본 문자열: ' || input_string);

       -- RANDOMBYTES 함수를 사용해 암호화 키 생성
       key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES (num_key_bytes);

       -- ENCRYPT 함수로 암호화를 한다. 원본 문자열을 UTL_I18N.STRING_TO_RAW를 사용해 RAW 타입으로 변환한다.
       encrypted_raw := DBMS_CRYPTO.ENCRYPT ( src => UTL_I18N.STRING_TO_RAW (input_string, 'AL32UTF8'),
                                              typ => encryption_type,
                                              key => key_bytes_raw
                                            );

       -- 암호화된 RAW 데이터를 한번 출력해보자
       DBMS_OUTPUT.PUT_LINE('암호화된 RAW 데이터: ' || encrypted_raw);
       -- 암호화 한 데이터를 다시 복호화 ( 암호화했던 키와 암호화 슈트는 동일하게 사용해야 한다. )
       decrypted_raw := DBMS_CRYPTO.DECRYPT ( src => encrypted_raw,
                                              typ => encryption_type,
                                              key => key_bytes_raw
                                            );

       -- 복호화된 RAW 타입 데이터를 UTL_I18N.RAW_TO_CHAR를 사용해 다시 VARCHAR2로 변환
       output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');

       -- 복호화된 문자열 출력
       DBMS_OUTPUT.PUT_LINE ('복호화된 문자열: ' || output_string);
    END;

결과

    원본 문자열: The Oracle
    암호화된 RAW 데이터: 139CA77B810FDCF9AC0B2113D8FCCF67
    복호화된 문자열: The Oracle

결과를 보면 ‘The Oracle’이란 문자열을 ENCRYPT 함수를 사용해 RAW 타입(139CA77B810FDCF9AC0B2113D8FCCF67)으로 암호화 한 후, 이를 다시 DECRYPT 함수를 사용해 복호화했다. 암호화하려면 키가 필요한데 키 값은 RANDOMBYTES 함수를 사용해 생성했고 암호화 알고리즘은 AES를 사용했다. 다시 한 번 말하지만 암호화된 데이터를 복호화하려면 암호화 할 때 사용했던 키와 암호화 슈트를 사용해서 복호화해야 한다.

ENCRYPT나 DECRYPT 프로시저는 암호화 대상 데이터, 암호화 및 복호화된 데이터를 BLOB로 변환해야 하는데 보통 암호화 대상 데이터는 문자나 숫자형이 대부분이며 이를 BLOB 타입으로 변환하는 것은 매우 번거롭다. 따라서 보통은 프로시저 대신 ENCRYPTDECRYPT 함수를 사용한다.

이번에는 단방향 암호화 해시 함수인 HASH와 MAC 함수를 사용해 보자. 이 함수는 단방향이므로 복호화가 매우 어렵고 통상 입력 값에 따라 암호화된 데이터를 비교함으로써 입력 값을 검증하는 데 사용된다.

입력

    DECLARE
      input_string  VARCHAR2 (200) := 'The Oracle';  -- 입력 VARCHAR2 데이터
      input_raw     RAW(128);                        -- 입력 RAW 데이터

      encrypted_raw RAW (2000); -- 암호화 데이터

      key_string VARCHAR2(8) := 'secret';  -- MAC 함수에서 사용할 비밀 키
      raw_key RAW(128) := UTL_RAW.CAST_TO_RAW(CONVERT(key_string,'AL32UTF8','US7ASCII')); -- 비밀키를 RAW 타입으로 변환

    BEGIN
      -- VARCHAR2를 RAW 타입으로 변환
      input_raw := UTL_I18N.STRING_TO_RAW (input_string, 'AL32UTF8');

      DBMS_OUTPUT.PUT_LINE('----------- HASH 함수 -------------');
    encrypted_raw := DBMS_CRYPTO.HASH( src => input_raw,
                                         typ => DBMS_CRYPTO.HASH_SH1);

      DBMS_OUTPUT.PUT_LINE('입력 문자열의 해시값 : ' || RAWTOHEX(encrypted_raw));

      DBMS_OUTPUT.PUT_LINE('----------- MAC 함수 -------------');
      encrypted_raw := DBMS_CRYPTO.MAC( src => input_raw,
                                        typ => DBMS_CRYPTO.HMAC_MD5,
                                        key => raw_key);

      DBMS_OUTPUT.PUT_LINE('MAC 값 : ' || RAWTOHEX(encrypted_raw));
    END;

결과

    ----------- HASH 함수 -------------
    입력 문자열의 해시값 : B095432571F215D1B60DDFCAEA9E483F5E24A084
    ----------- MAC 함수 -------------
    MAC 값 : 10722EA8E9CB57CE953E576D30D87260

HASH

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.