¿Cuál es la mejor manera de cifrar un clob?
-
01-07-2019 - |
Pregunta
Estoy usando Oracle 9 y JDBC y me gustaría cifrar un clob a medida que se inserta en la base de datos.Idealmente, me gustaría poder simplemente insertar el texto sin formato y cifrarlo mediante un procedimiento almacenado:
String SQL = "INSERT INTO table (ID, VALUE) values (?, encrypt(?))";
PreparedStatement ps = connection.prepareStatement(SQL);
ps.setInt(id);
ps.setString(plaintext);
ps.executeUpdate();
No se espera que el texto plano supere los 4000 caracteres, pero el cifrado alarga el texto.Nuestro enfoque actual de cifrado utiliza dbms_obfuscation_toolkit.DESEncrypt() pero solo procesamos varchars.¿Funcionará lo siguiente?
FUNCTION encrypt(p_clob IN CLOB) RETURN CLOB
IS
encrypted_string CLOB;
v_string CLOB;
BEGIN
dbms_lob.createtemporary(encrypted_string, TRUE);
v_string := p_clob;
dbms_obfuscation_toolkit.DESEncrypt(
input_string => v_string,
key_string => key_string,
encrypted_string => encrypted_string );
RETURN UTL_RAW.CAST_TO_RAW(encrypted_string);
END;
Estoy confundido acerca del golpe temporal;¿Necesito cerrarlo?¿O estoy totalmente desviado?
Editar:El propósito de la ofuscación es evitar el acceso trivial a los datos.Mi otro propósito es ofuscar los clobs de la misma manera que ya estamos ofuscando las columnas varchar.El código de muestra de Oracle no trata con clobs, que es donde radica mi problema específico;cifrar varchars (menos de 2000 caracteres) es sencillo.
Solución
Observo que está en Oracle 9, pero solo para que conste en Oracle 10g+, dbms_obfuscation_toolkit quedó obsoleto en favor de dbms_crypto.
dbms_crypto incluye soporte CLOB:
DBMS_CRYPTO.ENCRYPT(
dst IN OUT NOCOPY BLOB,
src IN CLOB CHARACTER SET ANY_CS,
typ IN PLS_INTEGER,
key IN RAW,
iv IN RAW DEFAULT NULL);
DBMS_CRYPT.DECRYPT(
dst IN OUT NOCOPY CLOB CHARACTER SET ANY_CS,
src IN BLOB,
typ IN PLS_INTEGER,
key IN RAW,
iv IN RAW DEFAULT NULL);
Otros consejos
Hay un ejemplo en la documentación de Oracle:
http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96612/d_obtoo2.htm
No es necesario cerrarlo
DECLARE
input_string VARCHAR2(16) := 'tigertigertigert';
raw_input RAW(128) := UTL_RAW.CAST_TO_RAW(input_string);
key_string VARCHAR2(8) := 'scottsco';
raw_key RAW(128) := UTL_RAW.CAST_TO_RAW(key_string);
encrypted_raw RAW(2048);
encrypted_string VARCHAR2(2048);
decrypted_raw RAW(2048);
decrypted_string VARCHAR2(2048);
error_in_input_buffer_length EXCEPTION;
PRAGMA EXCEPTION_INIT(error_in_input_buffer_length, -28232);
INPUT_BUFFER_LENGTH_ERR_MSG VARCHAR2(100) :=
'*** DES INPUT BUFFER NOT A MULTIPLE OF 8 BYTES - IGNORING
EXCEPTION ***';
double_encrypt_not_permitted EXCEPTION;
PRAGMA EXCEPTION_INIT(double_encrypt_not_permitted, -28233);
DOUBLE_ENCRYPTION_ERR_MSG VARCHAR2(100) :=
'*** CANNOT DOUBLE ENCRYPT DATA - IGNORING EXCEPTION ***';
-- 1. Begin testing raw data encryption and decryption
BEGIN
dbms_output.put_line('> ========= BEGIN TEST RAW DATA =========');
dbms_output.put_line('> Raw input : ' ||
UTL_RAW.CAST_TO_VARCHAR2(raw_input));
BEGIN
dbms_obfuscation_toolkit.DESEncrypt(input => raw_input,
key => raw_key, encrypted_data => encrypted_raw );
dbms_output.put_line('> encrypted hex value : ' ||
rawtohex(encrypted_raw));
dbms_obfuscation_toolkit.DESDecrypt(input => encrypted_raw,
key => raw_key, decrypted_data => decrypted_raw);
dbms_output.put_line('> Decrypted raw output : ' ||
UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw));
dbms_output.put_line('> ');
if UTL_RAW.CAST_TO_VARCHAR2(raw_input) =
UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw) THEN
dbms_output.put_line('> Raw DES Encyption and Decryption successful');
END if;
EXCEPTION
WHEN error_in_input_buffer_length THEN
dbms_output.put_line('> ' || INPUT_BUFFER_LENGTH_ERR_MSG);
END;
dbms_output.put_line('> ');
Ligeramente fuera de tema:¿Cuál es el punto del cifrado/ofuscación en primer lugar?Un atacante que tenga acceso a su base de datos podrá obtener el texto sin formato; encontrar el procedimiento almacenado anterior le permitirá al atacante realizar el descifrado.