사용자 도구

사이트 도구


database:oracle:dbms_crypto

Oracle DMBS Crypto

  • DB 의존적인 암호화 코드 사용은 절대 비권장

활성화 및 권한 부여

Oracle 에 SYS 계정으로 접근하여

@$ORACLE_HOME/rdbms/admin/dbmsobtk.sql
@$ORACLE_HOME/rdbms/admin/prvtobtk.plb
 
GRANT EXECUTE ON dbms_crypto TO [계정명];
GRANT EXECUTE ON dbms_obfuscation_toolkit TO [계정명];
 
-- 모든 사용자에게 권한 추가
-- grant execute on dbms_crypto to public;
-- grant execute on dbms_obfuscation_toolkit to public;

함수

  • DBMS_CRYPTO.ENCRYPT : 암호화 수행. 암호화 데이터 인자로 byte 배열(RAW)를 받음. byte 배열(RAW) 반환.
  • DBMS_CRYPTO.DECRYPT : 복호화 수행. 복호화 데이터 인자로 hex 문자열 받음. byte 배열(RAW) 반환.

DBMS_CRYOPTO 상수 읽기

  • DBMS_CRYPTO.* 의 상수들은 PL/SQL 블럭에서만 읽을 수 있다.
BEGIN
    dbms_output.put_line(dbms_crypto.DES_CBC_PKCS5);
END;
/

알고리즘

  • Oracle dbms_crypto.DES_CBC_PKCS5 → Java DES/CBC/PKCS5Padding

Key

  • 암호화의 비밀번호

Vector

  • CBC 모드 등에서 필요하다.
  • 필수는 아니다.
  • 벡터가 필요 없는 상황에서 Java 는 아래와 같이 empty vector 를 사용하면 된다.
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);

Oracle 암호화 -> Java 복호화

-- byte 배열(RAW) 결과
SELECT DBMS_CRYPTO.encrypt(UTL_RAW.CAST_TO_RAW ('Secret Data'), 4353
, UTL_RAW.CAST_TO_RAW ('MYKEY123'),UTL_RAW.CAST_TO_RAW('01234567')) FROM dual;
 
-- VARCHAR2 로 cast 하면 hex 문자열이 나온다.
SELECT CAST(DBMS_CRYPTO.encrypt(UTL_RAW.CAST_TO_RAW ('Secret Data'), 4353, UTL_RAW.CAST_TO_RAW ('MYKEY123'),UTL_RAW.CAST_TO_RAW('01234567')) AS VARCHAR2(100)) FROM dual;
-- 결과 : 963C9ABD5C20382996DF9E0849F28C45
  • UTL_RAW.CAST_TO_RAW ('Secret Data') 암호화할 데이터(Secret Data)를 binary로
    • 유니코드의 경우 UTL_I18N.STRING_TO_RAW('암호화할 데이터', 'AL32UTF8') 형태로 UTF-8 byte로.
    • 유니코드에서 RAW(byte[])를 다시 문자열로 변경은 UTL_I18N.RAW_TO_CHAR('RAW 데이터', 'AL32UTF8')
  • 4353 알고리즘 ID : dbms_crypto.DES_CBC_PKCS5 값이다. 이는 사실 여러 알고리즘을 나타내는DBMS_CRYPTO.상수 들의 합이다.
  • UTL_RAW.CAST_TO_RAW ('MYKEY123') : 비밀번호(Key) binary
  • UTL_RAW.CAST_TO_RAW('01234567') Vector. 선택적임.

위와 같이 암호화된 데이터를 Java 로 복호화

public void testDecryption() {
  String CIPHER = "DES/CBC/PKCS5Padding";
 
  byte[] key = DatatypeConverter.parseHexBinary("4D594B4559313233"); // "MYKEY123".getBytes("UTF-8") 와 같다.
  byte[] value =
     DatatypeConverter.parseHexBinary("963C9ABD5C20382996DF9E0849F28C45"); // 암호화 결과의 hex 
  String INIT_VECTOR =
     new String(DatatypeConverter.parseHexBinary("3031323334353637"));
  SecretKeySpec secretKeySpec=new SecretKeySpec(key, "DES");
  IvParameterSpec ivParameterSpec=null;
  try {
    ivParameterSpec=new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
  } catch (UnsupportedEncodingException e1) {
    e1.printStackTrace();
  }
  Cipher decryptCipher=null;
  try {
    decryptCipher= Cipher.getInstance(CIPHER);
    decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec,ivParameterSpec);
  } catch (NoSuchAlgorithmException | NoSuchPaddingException |InvalidKeyException
| InvalidAlgorithmParameterException  e) {
    e.printStackTrace();
  }
  String result="";
  try {
    result=new String(decryptCipher.doFinal(value),Charset.forName("UTF-8"));
  } catch (IllegalBlockSizeException e) {
    e.printStackTrace();
  } catch (BadPaddingException e) {
    e.printStackTrace();
  }
  System.out.println("Result " + result); //   Result Secret Data
}
byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);
 
// 혹은 apache commons codec
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));

참조

database/oracle/dbms_crypto.txt · 마지막으로 수정됨: 2020/08/11 16:49 저자 kwon37xi