Encriptación de datos desde aplicación.
En todos los ejemplos que he encontrado sobre encriptación y desencriptación de datos en Oracle, siempre se usan procedimientos PL/SQL para establecer la seguridad en la base de datos. No he encontrado un sólo ejemplo que permita hacer un insert «encriptado» y una consulta «desencriptada».
Imaginando el siguiente escenario: Cada usuario tiene una «palabra secreta» para desencriptar su propia información. En la base de datos todo se registra encriptado.
Para ello, Oracle ofrece dos paquetes:
– DBMS_OBFUSCATION_TOOLKIT. A partir de Oracle8i, que soporta encriptación DES y triple DES (Data Encription Standard), y con ciertas limitaciones (por ejemplo, los datos a encriptar han de ser un múltiplo de 8 bytes).
– DBMS_CRYPTO. A partir de Oracle10g. Soporta más formas de encriptación, como la AES (Advanced Encription Standard), que sustituye el anterior DES y no hay limitación con el número de carácteres.
Para mas información, la documentación de Oracle ofrece esta comparativa de funcionalidades.
El siguiente ejemplo muestra la encriptación de la palabra «SECRETO» (8 bytes) y genera un error al intentar encriptar «SECRETITOS!» (11 bytes)
SQL> select DBMS_OBFUSCATION_TOOLKIT.
DBMS_OBFUSCATION_TOOLKIT.
——————————
lr??
SQL> select DBMS_OBFUSCATION_TOOLKIT.
select DBMS_OBFUSCATION_TOOLKIT.
*
ERROR at line 1:
ORA-28232: invalid input length for obfuscation toolkit
ORA-06512: at «SYS.DBMS_OBFUSCATION_TOOLKIT_
ORA-06512: at «SYS.DBMS_OBFUSCATION_TOOLKIT»
El error ORA-28232 corresponde a la longitud inadecuada de la cadena a encriptar. ‘SECRETITOS!» tiene 11 carácteres y el paquete está limitado a múltiplos de 8 bytes. Por ejemplo, el número de una tarjeta de crédito.
SQL> select DBMS_OBFUSCATION_TOOLKIT.DESEncrypt(input_string=>’1234567812345678′,
2 key_string=>’clavedesencript’)
3 from dual;
DBMS_OBFUSCATION_TOOLKIT.DESENCRYPT(INPUT_STRING=>’1234567812345678′,KEY_STRING=
——————————————————————————–
}??X??
De modo que la desencriptación funciona de igual modo, usando la función DESDecrypt
SQL> select DBMS_OBFUSCATION_TOOLKIT.
2 input_string=>DBMS_
3 key_string=>’CLAVE_BUENA’) from dual;
DBMS_OBFUSCATION_TOOLKIT.
——————————
SECRETO!
SQL> select DBMS_OBFUSCATION_TOOLKIT.DESDecrypt(
2 input_string=>DBMS_OBFUSCATION_TOOLKIT.DESEncrypt(input_string=>’1111222233334444′,key_string=>’CLAVE_BUENA’),
3 key_string=>’CLAVE_BUENA’) from dual;
DBMS_OBFUSCATION_TOOLKIT.DESDECRYPT(INPUT_STRING=>DBMS_OBFUSCATION_TOOLKIT.DESEN
——————————————————————————–
1111222233334444
y si se utiliza una clave distinta, la información no se desencriptará adecuadamente.
SQL> select DBMS_OBFUSCATION_TOOLKIT.
2 input_string=>DBMS_
3 key_string=>’CLAVE_ERRONEA’) from dual;
DBMS_OBFUSCATION_TOOLKIT.
——————————
???! k
…ó producirá un error.
SQL> select DBMS_OBFUSCATION_TOOLKIT.DESDecrypt(
2 input_string=>DBMS_OBFUSCATION_TOOLKIT.DESEncrypt(input_string=>’1111222233334444′,key_string=>’CLAVE_BUENA’),
3 key_string=>’CLAVE_MALA’) from dual;
ERROR:
ORA-29275: partial multibyte character
no rows selected
El siguiente ejemplo muestra la encriptación de la palabra «SECRETITOS!» (11 bytes) usando una suite de encriptación que ya viene implementada. En concreto es la DES_CBC_PCKS5, que contiene encriptación DES, encadenamiento de cifrado de bloques y modificadores de relleno PCKS5.
Es preciso, para invocar correctamente a este paquete, realizar una conversión a RAW de las cadenas a encriptar. He utilizado para ello el paquete UTL_RAW y la función UTL_I18N.STRING_TO_RAW.
SQL> select DBMS_CRYPTO.ENCRYPT(src => UTL_I18N.STRING_TO_RAW (‘SECRETITOS!’, ‘AL32UTF8’),
2 typ => 4353,
3 key => UTL_I18N.STRING_TO_RAW (‘clavedesencript’, ‘AL32UTF8’)
4 )
5 from dual;
DBMS_CRYPTO.ENCRYPT(SRC=>UTL_
——————————
1BA7F933C2CAD0C7F4FDA685775BE0
Y la desencriptación de la información, con la función DECRYPT.
SQL> select UTL_RAW.cast_to_varchar2(
2 DBMS_CRYPTO.DECRYPT(
3 DBMS_CRYPTO.ENCRYPT(src => UTL_I18N.STRING_TO_RAW (‘SECRETITOS!’, ‘AL32UTF8’),
4
5
6
7 typ => 4353,
8 key => UTL_I18N.STRING_TO_RAW (‘clavedesdecript’, ‘AL32UTF8’)
9 )
10 )
11 from dual;
UTL_RAW.CAST_TO_VARCHAR2(DBMS_
——————————
SECRETITOS!
Para más información sobre las múltiples formas de encriptación y uso de claves, lo mejor es consultar la documentación del paquete DBMS_CRYPTO.
Comments
Sergio Luna
Muchas gracias por tu ayuda!!!
Sigue así con este magnífico blog.
Un saludo
Javier Morales
Gracias a ti, Sergio!
Un abrazo,
Anónimo
Hola Javier, Cordial Saludo. Excelente tu explicacion y gracias por ello. Tengo una inquietud: utilizando DBMS_CRYPTO puedo controlar la longitud de la cadana encriptada ? Cordialmente, Jesus Franco.
Anónimo
Hola Javier, gracias por tu ejemplo, es excelente. Tengo una inquietud al respecto, es posible controlar la longitud de la cadena encriptada que retorna DBMS_CRYPTO.ENCRYPT ? o como puedo determinar el largo de la cadana ecriptada. Gracias de nuevo. Jesus Franco
Javier Morales
Hola Jesús,
El paquete de encriptación retorna un tipo RAW, que es de longitud fija.
🙂
Anónimo
El uso de DBMS_CRYPTO requiere de una licencia adicional?
Javier Morales
Hola Anónimo,
No hace falta licencia adicional. Es un paquete suministrado de PL/SQL como DBMS_OUTPUT o UTL_FILE.
Consulta con tu DBA si tienes algún problema al ejecutarlo, porque quizás tenga que concederte permisos para usarlo.
Un saludo
William
Hola Javier, se puede utilizar decode o case when en el where de un select,
select * from tabla1 where case when(tabla1.campo1=.t.) then … else … end
Javier Morales
Hola William,
Si.
Doc. Oracle sobre Case.
Un saludo,
Javier
Víctor López
Perfecto,
es exactamente lo que estaba buscando. Y como seguimos utilizando Oracle 10 no hay ningún problema por que la entrada sea de hace cinco años ;-).
Saludos.
Javier
Este comentario ha sido eliminado por el autor.
Javier Morales
Hola Víctor!
Muchas gracias por tu comentario!
Solo añadir que el paquete DBMS_CRYPTO se sigue usando en Oracle12c! 🙂
Un saludo,
Javier