en portada Seguridad y cifrado de datos en DB2

Seguridad y cifrado de datos en DB2

Por Kent Milligan

Un rollo de seguridad

Las normas relativas a la confiden­cia­lidad de los datos y los informes de identificación de robos de datos han aumentado la concienciación sobre la seguridad en nuestros departamentos de TI y en nuestros hogares. Este mayor interés está obligando a los programadores y admi­nistradores de iSeries a pensar en nuevos métodos de protección de los datos confidenciales que se guardan en sus bases de datos. El release V5R3 ofrece nuevas formas de protección gracias a las funciones de cifrado y descifrado de DB2.

Antes de aplicar ningún método nuevo de protección, es importante no descuidar el primer paso para proteger los datos de DB2: la seguridad a nivel de objetos. El empleo de los sólidos servicios de seguridad a nivel de objetos de i5/OS es crucial a la hora de asegurar la protección de los datos de DB2, sea cual sea la interfaz que se utilice para acceder a los mismos. Los usuarios finales exigen cada vez más interfaces para acceder a los datos, de modo que los departamentos que trabajan con iSeries no pueden confiar en la seguridad basada en menús para controlar el acceso a datos confidenciales. La seguridad a nivel de objetos impide que los usuarios sin autorización puedan acceder o modificar datos financieros confidenciales de la empresa (por ejemplo, datos sobre los salarios).

El cifrado de datos es un método de seguridad que puede utilizarse para ofrecer otra capa de protección a las columnas de DB2 que contienen datos confidenciales. Esta capa adicional de seguridad es necesaria porque la seguridad a nivel de objetos no puede evitar que los usuarios autorizados, como por ejemplo el personal del servicio de asistencia técnica, puedan consultar datos confidenciales o que un hacker los lea utilizando las credenciales (ID y contraseña) robadas de un usuario. Si los datos confidenciales como el número de la tarjeta de crédito se almacenan en un formato cifrado, todos los usuarios recibirán una serie binaria de datos cifrados de forma predeterminada. Para ver el número real de la tarjeta de crédito, el usuario necesitará tener autorización para acceder al objeto de DB2, así como a la contraseña de cifrado y a la función de descifrado.

Vamos a ver un ejemplo que nos permitirá saber cómo utilizar las nuevas funciones de cifrado y descifrado de DB2 en este caso hipotético para proporcionar una capa adicional de seguridad:

SET ENCRYPTION PASSWORD = 'SECRETO'
INSERT INTO cliente
  VALUES('JOSE',
  ENCRYPT('1111222233334444'))
SET ENCRYPTION PASSWORD = 'SECRETO'
SELECT nombre,
  DECRYPT_CHAR(num_tarj)
  FROM cliente

En el código anterior, la sentencia Set Encryption Password proporciona a DB2 la clave que se utilizará para cifrar (y descifrar) los datos. En la sentencia siguiente se muestra cómo se utiliza la función de cifrado de DB2 para codificar el número de la tarjeta de crédito antes de grabarlo en la tabla de DB2. La última sentencia muestra los pasos necesarios para ver el valor original del número de la tarjeta de crédito, '1111222233334444'. En primer lugar, la clave de cifrado debe ser la misma que la que se utilizó para cifrar el número. Después, debe utilizarse una de las funciones de descifrado de DB2 para convertir el valor binario cifrado en el valor original de tipo carácter.

Una de las cosas más importantes que hay que observar en este ejemplo es que no hay palabras clave de SQL o DDS que indiquen a DB2 UDB que cifre o descifre automáticamente los datos. Hay que realizar cambios en la aplicación. La razón es que el cifrado y descifrado automático no ofrece una capa adicional de seguridad. Si DB2 descifra automáticamente el número de la tarjeta de crédito para todos los usuarios que lean la tabla de clientes, entonces dicho número sería visible para los mismos usuarios que antes de cifrarlo. Únicamente podrá sacar partido de la seguridad que ofrece el cifrado si cambia las aplicaciones y las interfaces para que descifren de forma selectiva los datos para un subconjunto de usuarios autorizados. El valor añadido que proporciona DB2 es que esas nuevas funciones facilitan el cifrado y descifrado de los datos. Las aplicaciones pueden llamar a una simple función de SQL en lugar de tener que programar llamadas a complejas API y servicios criptográficos.

Prepararse para el cifrado de datos
Ahora que ya sabe cómo pueden utilizarse las nuevas funciones de cifrado y descifrado, vamos a centrarnos en los pasos necesarios para configurarlas.

En primer lugar, hay que indicar que se trata de un producto gratuito que no se necesita instalar en el servidor. Las funciones de cifrado y descifrado de columnas de DB2 UDB realmente utilizan los algoritmos de cifrado integrados en el producto de IBM Proveedor de acceso criptográfico de 128 bits para iSeries (5722-AC3). Ni el Coprocesador ni el Acelerador criptográficos de IBM son necesarios y no ofrecen ninguna ventaja sobre los algoritmos de cifrado utilizados por DB2 UDB.

El último paso de configuración es identificar las columnas que se desean cifrar. El cifrado de datos exige cambiar el tipo y la longitud de los datos en las definiciones de columna existentes. El tipo de datos debe cambiarse porque un valor cifrado es una serie binaria que solamente puede almacenarse en una columna definida con uno de los tipos siguientes:

- BINARY
- VARBINARY
- CHAR FOR BIT DATA
- VARCHAR FOR BIT DATA
- BLOB

Si la tabla de DB2 UDB de destino se define con DDS, entonces la columna de destino debe definirse como un campo de tipo carácter de longitud variable con un valor de CCSID de 65535.

La longitud de una columna existente deberá aumentarse porque se necesitan algunos bits de más para el valor cifrado. Esta longitud también ha de incrementarse si con el valor cifrado se almacena una pista para recordar la contraseña (este tema lo trataremos en breve).

La longitud real de un valor de tipo serie de caracteres cifrada es la longitud de la serie más n bytes, definiéndose n como sigue:

- Si no se especifica una pista para recordar la contraseña, n valdrá 8 bytes (o 16 bytes si la serie de entrada es de tipo LOB, BINARY o VARBINARY, o si la serie de entrada y la contraseña tienen valores de CCSID distintos), más el número de bytes que hay hasta el siguiente límite de 8 bytes.
- Si se especifica una pista para recordar la contraseña, n valdrá 8 bytes (16 bytes si la serie de entrada es de tipo LOB, BINARY o VARBINARY, o si la serie de entrada y la contraseña tienen valores de CCSID distintos), más el número de bytes que hay hasta el siguiente límite de 8 bytes, más 32 bytes para la pista para recordar la contraseña.

Si los valores de CCSID son distintos, puede ocurrir que a la contraseña se le asigne el CCSID utilizado por el trabajo y que al valor cifrado se le asigne el CCSID del tipo de datos del resultado. A continuación se ofrecen un par de ejemplos para entender mejor los requisitos de longitud:

Un número de tarjeta de crédito de 16 dígitos que se almacenará en una columna de tipo VARBINARY sin una pista para recordar la contraseña necesitará que la longitud de la columna sea de 32 bytes. Es decir, 16 bytes para los datos sin cifrar + 16 bytes adicionales + 0 bytes adicionales (ya es un límite de 8 bytes).

Un número de la Seguridad Social de nueve dígitos que se almacenará en una columna de tipo VARCHAR FOR BIT DATA con una pista para recordar la contraseña necesitará tener una longitud de columna de 56 bytes. 9 bytes para los datos sin cifrar + 8 bytes adicionales + 7 bytes adicionales (para llegar al siguiente límite de 8 bytes) + 32 bytes para la pista.

A parte de minimizar el número de cambios en la definición de columna, otra razón para cifrar sólo un pequeño subconjunto de columnas es el impacto en el rendimiento. Por ejemplo, si se aumentara la seguridad del bloque de oficinas añadiendo un lector de tarjetas de identificación en la puerta principal, los trabajadores tardarían un poco más en llegar a sus escritorios todas las mañanas. El resultado de añadir las funciones de cifrado y descifrado a una aplicación es que el acceso a la base de datos es algo más lento.

La receta del cifrado
Ahora que ya hemos hecho todos los preparativos, es el momento de aprender a utilizar la función de cifrado de DB2. El primer paso para el cifrado de datos es suministrar a DB2 una clave de cifrado. La contraseña de cifrado puede establecerse en el trabajo o en la conexión con la sentencia Set Encryption Password. Esta sentencia es un buen método cuando la misma contraseña se ha de compartir entre varias filas de una tabla o entre distintas tablas.

La contraseña de cifrado es una serie de caracteres que debe tener una longitud de entre 6 y 127 bytes, y su valor no distingue entre mayúsculas y minúsculas. Para ayudar a los administradores y a los programadores a recordar el valor de la contraseña, la sentencia Set Encryption Password permite guardar opcionalmente una pista para recordar la contraseña (de hasta 32 bytes) junto con el valor cifrado de los datos. El ejemplo siguiente muestra cómo suministrar a DB2 una clave de cifrado y una pista para recordar la contraseña:

CREATE TABLE trab (
  seguridadSocial 
  VARCHAR FOR BIT DATA(56)
  nombre VARCHAR(30))

SET ENCRYPTION PASSWORD=
  'atlantico' WITH HINT='oceano'
INSERT INTO trab VALUES(
  ENCRYPT('123456789'), 'JOANA')

SELECT GETHINT(
  seguridadSocial) FROM trab

La sentencia Set Encryption Password especifica "atlantico" como valor de la clave de cifrado, siendo "oceano" la pista para recordar la contraseña. Cuando la sentencia Insert cifra el número de la Seguridad Social del trabajador, DB2 UDB también almacena en esa columna la pista con el valor cifrado. Si un administrador se olvida alguna vez de la clave de cifrado, puede utilizar la función GetHint de DB2 para recuperar el valor de la pista, "oceano" con lo que debería recordar que para la clave de cifrado se utilizó el nombre de un océano. La clave de cifrado especificada en la sentencia Set Encryption Password estará activa hasta que el trabajo o grupo de activación finalicen.

También se puede activar o desactivar la contraseña de cifrado en distintas filas de una tabla ejecutando la sentencia Set Password varias veces o especificando el valor de la contraseña en la función Encrypt de DB2. La función Encrypt admite tres parámetros de entrada, pero el único obligatorio es la serie de datos de entrada. Los parámetros opcionales son la contraseña y la pista para recordarla. A continuación puede verse un ejemplo de cómo llevar a cabo el mismo cifrado que en el ejemplo anterior:

INSERT INTO trab VALUES(
  ENCRYPT('123456789',
  'atlantico', 'oceano'),
  'JOANA')

En ambos ejemplos se demuestra que DB2 UDB admite un sinónimo de ENCRYPT porque el nombre formal de la función realmente es ENCRYPT_RC2. RC2 se utiliza en el nombre de la función para indicar que durante el proceso de cifrado se utiliza un cifrado por bloques RC2 con el algoritmo de cifrado con relleno. La función Encrypt calcula una clave secreta de 128 bits a partir de la contraseña utilizando un resumen de mensaje MD5.

Obviamente, no es una buena idea codificar la contraseña de cifrado y la pista para recordarla en el código fuente de la aplicación. El método recomendado es suministrar esos valores mediante variables del sistema principal o mediante marcadores de parámetros para que la contraseña de cifrado sea menos visible para alguien que examine el código fuente de la aplicación:

SET ENCRYPTION PASSWORD=
  :varsispral1 WITH HINT=:varsispral2

INSERT INTO trab VALUES(
  ENCRYPT(‘123456789’,?,?), ‘JOANA’)

Si la aplicación gestiona el cifrado y descifrado de los datos, puede proteger aún más el valor de la contraseña almacenándolo en un objeto de tipo lista de validación y recuperándolo cuando sea necesario. Los objetos de tipo lista de validación son preferibles antes que otros tipos de objetos como los espacios de usuario o las áreas de datos, porque permiten que una parte de la entrada de la lista esté cifrada. Esto posibilita que la contraseña de cifrado se almacene de forma segura en un formato cifrado.

En ocasiones, puede ser una buena idea crear índices de datos cifrados. Las búsquedas exactas y las operaciones de unión de datos cifrados utilizarán los índices que se creen. Como los datos cifrados son, básicamente, datos binarios, la comprobación de rangos de datos cifrados requerirá hacer búsquedas en la tabla y debe evitarse siempre que sea posible.

En caso de que deban hacerse búsquedas en una columna cifrada, debería utilizar las funciones de cifrado de forma que se minimice el número de valores que han de descifrarse en las búsquedas. Por ejemplo, la forma óptima de buscar un usuario por su número de la Seguridad Social es la consulta siguiente, porque evita descifrar todos los números de la Seguridad Social de la tabla:

SELECT nombre FROM trab
  WHERE seguridadSocial=
  ENCRYPT(‘123456789’);

Descifrado: desbloquear los datos
El último paso de este proceso de protección de los datos es volver a obtener el valor original de los datos con la función de descifrado de DB2 UDB. En el release V5R3 se incluye el siguiente juego de funciones de descifrado:

- DECRYPT_CHAR
- DECRYPT_DB
- DECRYPT_BIT
- DECRYPT_BINARY

Como devuelven una serie de caracteres, las funciones DECRYPT_CHAR y DECRYPT_DB probablemente sean las que más se usan. Como ocurre con la función Encrypt, las funciones Decrypt aceptan hasta tres parámetros, pero sólo el primero es obligatorio. El primer parámetro obviamente identifica el valor cifrado que ha de descifrarse. El segundo parámetro puede utilizarse para especificar la contraseña y el último es un valor entero que puede servir para especificar el valor de CCSID de los valores de las series de caracteres que se devuelvan.

Para que las funciones de descifrado devuelvan el valor original, la contraseña de cifrado debe ser la misma que se utilizó para cifrar los datos con la función Encrypt. Si es distinta, se devolverá un error de ejecución. A continuación, puede verse un ejemplo que muestra cómo descifrar los datos cifrados en el primer ejemplo:

SET ENCRYPTION PASSWORD=
  ‘atlantico’

SELECT DECRYPT_CHAR(
  seguridadSocial) FROM trab
  WHERE nombre=’JOANA’

Las aplicaciones que lean el número de la Seguridad Social de la tabla de trabajadores sin la función de descifrado recibirán por omisión el valor de la serie binaria cifrada.

Como puede ver, llamar a las funciones de descifrado de DB2 es fácil. El auténtico desafío está en diseñar un proceso y unas herramientas que distribuyan de forma selectiva las claves de cifrado a los usuarios que están autorizados a ver la versión sin cifrar de los datos. Los desarrolladores de aplicaciones y los administradores de seguridad deben trabajar juntos para diseñar el mejor proceso para las aplicaciones y la empresa.

Una opción es exigir a todos los usuarios de los datos que escriban manualmente la contraseña de cifrado. Se necesita una infraestructura adicional para almacenar y gestionar la contraseña del usuario (por ejemplo, para poder recuperar las contraseñas y las pistas para recordarlas).

Interfaces nativas y cifrado de DB2
Las aplicaciones que utilizan la interfaz nativa (no SQL) también pueden sacar partido de esta nueva función de DB2. A lo largo del proceso, necesitará utilizar algo de SQL, pero eso no quiere decir que tenga que volver a escribir sus aplicaciones para que utilicen SQL. Los usuarios de interfaces nativas han de entender que la tabla subyacente que contendrá los datos cifrados no tiene porqué crearse con SQL. La columna que se va a cifrar sólo ha de satisfacer los requisitos que se han comentado antes.

Los desencadenantes de la base de datos son una forma excelente de poner a disposición de todo el mundo los servicios de cifrado sin tener que modificar todas las aplicaciones para que utilicen SQL. Es posible definir los desencadenantes Before Insert y Update para que intercepten las peticiones de grabación a la base de datos y que cifren los datos confidenciales de una columna antes de pasárselos al motor de DB2. La utilización de desencadenantes significa que el único programa que podrá utilizar SQL para llamar a la función ENCRYPT_RC2 es el programa desencadenante. Pueden utilizarse tanto desencadenantes de SQL como externos.

El ejemplo siguiente utiliza desencadenantes de SQL para cifrar los números de la Seguridad Social insertados en la tabla de trabajadores:

CREATE TRIGGER proteger_numeross
  BEFORE INSERT ON trab
REFERENCING NEW ROW AS n
FOR EACH ROW
BEGIN
  DECLARE clave_cifrado VARCHAR(127);
  SET clave_cifrado = obtener_contraseña
      UDF(‘TRAB’);
  SET n.seguridadSocial = ENCRYPT_RC2(
      n.seguridadSocial, clave_cifrado);
END

Una operación de grabación nativa (o una sentencia Insert de SQL) en la tabla de trabajadores llamará a este desencadenante Before Insert. Después, el desencadenante proteger_numeross de SQL llamará a la función definida por el usuario obtener_contraseñaUDF() para obtener la contraseña cifrada de la tabla de trabajadores. A continuación, se utilizará esta contraseña para cifrar el número de la Seguridad Social en la imagen anterior del registro que utiliza DB2 UDB con el fin de generar una fila nueva en la tabla de trabajadores.

Las vistas de SQL son probablemente el medio más utilizado para proporcionar a los programas nativos la capacidad de leer la versión descifrada de los datos confidenciales. Esta es una vista de ejemplo que puede utilizarse de esta forma:

CREATE VIEW my_logins(
  system, login, passwd) AS
  SELECT system,login,char(
    decrypt_char(passwd),6 )
  FROM regusers WHERE userid=USER

El programa nativo puede abrir la vista de SQL my_logins como un archivo lógico y la función de descifrado de la columna que contiene la vista de SQL permitirá devolver al programa nativo la versión sin cifrar de los datos de la columna. El descifrado se producirá solamente si el programa nativo ha establecido la clave de cifrado adecuada -directamente ejecutando la sentencia Set Encryption Password de SQL o indirectamente llamando a otro programa. La longitud de las columnas cifradas ha de ser mayor, de modo que los programas nativos tendrán que descifrar los datos o deberán modificarse para poder manejar esa longitud mayor cuando se devuelvan los datos cifrados.

¿Ha quedado claro?
El PTF de grupo de base de datos del release V5R3 más reciente incluye la compatibilidad con un nuevo tipo de desencadenante que hace aún más fácil la incorporación del cifrado y el descifrado en las aplicaciones. Este nuevo tipo de desencadenante se conoce como Instead Of (consulte el recuadro "Cifrado de DB2 y desencadenantes Instead Of", en la página 24).

Espero que tras leer este artículo le haya quedado claro cómo proteger mejor los datos confidenciales de su empresa con las funciones de cifrado de DB2.

Kent Milligan es un especialista en la tecnología DB2 UDB para iSeries de eServer Solutions Enablement. Los ocho primeros años que trabajó en IBM formó parte del equipo de desarrollo de DB2, en Rochester. Suele dar charlas y escribir artículos sobre cuestiones relacionadas con las bases de datos relacionales.

un anuncio
webgate400
Telefonica

  Con la colaboración de:

Partners