SQL Server, ideas y experiencias

Cómo validar un usuario con funciones de cifrado del SQL Server sin almacenar la contraseña en una tabla

por Jose Mariano Alvarez 6. julio 2009

Aunque usar mecanismos de autenticación propios no es lo más recomendable, podemos utilizar,  con cierta seguridad, las funciones de cifrado EncryptByPassPhrase y DecryptByPassPhrase incorporadas al T-SQL del SQL Server 2005 y SQL Server 2008 para implementar un mecanismo propio, que además no almacena ni siquiera la contraseña cifrada como mecanismo adicional de seguridad.

Para evitar que se pueda obtener la contraseña, vamos a utilizar un mecanismo que evita almacenarla y en su lugar vamos a utilizar un mecanismo de cifrado mediante clave simétrica que almacena, en su reemplazo, el usuario utilizando la contraseña ingresada por el usuario como frase de contraseña o clave de cifrado.  Esto prácticamente restringe los posible ataques a la prueba por fuerza bruta de la contraseña.

Se conoce a la frase de contraseña como una contraseña que incluye espacios. Dado los requerimientos de seguridad crecientes, que implican tener claves cada vez más complejas y grandes, la ventaja de usar una frase de contraseña es que es más fácil recordar una frase larga con significado que una cadena de caracteres larga. Las función EncryptByPassPhrase que vamos a usar para cifrar no comprueba la existencia de espacios en la frase de contraseña ni la complejidad de la contraseña, por lo que queda como responsabilidad del programador realizar esta comprobación.

Los parámetros de EncryptByPassPhrase son:

  • passphrase: Frase de contraseña a partir de la cual se genera una clave simétrica.
  • cleartext: Texto no cifrado que se va a cifrar.
  • add_authenticator: Indica si se cifrará un autenticador junto con el texto sin cifrar. 1 si se va a agregar un autenticador. int.
  • authenticator: Datos a partir de los cuales se obtiene un autenticador. sysname.

El resultado de la función es el dato cifrado el cual se obtiene como varbinary con un tamaño máximo de 8.000 bytes.

Este código crea una base de datos de ejemplo y una tabla que almacena los datos

use master
go

-- Creo una base de datos para la prueba
Create database Prueba
go
use Prueba
go

-- Creo una tabla de usuarios que no almacena 
-- la contraseña ni la contraseña cifrada
-- sino el usuario cifrado con la contraseña como 
-- clave de cifrado.
Create table dbo.Usuarios
(
    Usuario varchar(100) primary key,
    HashUsuario varbinary(8000)
)
go

Para agregar los datos del usuario usaremos el siguiente procedimiento almacenado que permite agregar al usuario con el correspondiente usuario cifrado para usar luego al validar las credenciales.

-- procedimiento para cifrar y guardar el usuario
Create procedure dbo.AgregarUsuario
    @Usuario varchar(100),
    @Contrasena varchar(100)
as 
Insert into Usuarios(Usuario,HashUsuario) 
values(
    @Usuario,
    EncryptByPassPhrase(@Contrasena ,@Usuario ,0)
)
GO

Se debe tener en cuenta que cada vez que se ejecuta la función EncryptByPassPhrase, aunque usemos los mismos parámetros, el resultado cifrado es diferente, por lo cual no se pueden comparar los resultados cifrados de dos ejecuciones y por lo tanto se debe utilizar la función de descifrado para validar.

La función de descifrado es DecryptByPassPhrase y los parámetros son:

  • passphrase: Frase de contraseña que se utilizará para generar la clave para el descifrado.
  • 'ciphertext':Es el texto cifrado que hay que descifrar. Es del tipo varbinary. El tamaño máximo es 8.000 bytes.
  • add_authenticator: Indica si se ha cifrado un autenticador junto con el texto simple. Es 1 si se ha utilizado un autenticador. int.
  • authenticator: Son los datos del autenticador. sysname.

El  Tipos de valor devueltos es varbinary con un tamaño máximo de 8.000 bytes. La función DecryptByPassPhrase  devuelve NULL si se utiliza la información de autenticador errónea o la frase de contraseña errónea.

Veamos el ejemplo para validar el usuario

-- Procediemiento para descifrar y validar
Create procedure dbo.ValidarUsuario
    @Usuario varchar(100),
    @Contrasena varchar(100)
as 
if (
    Select COUNT(*)
    from    Usuarios 
    where    Usuario = @Usuario
    and        cast(DECRYPTBYPASSPHRASE(@Contrasena,HashUsuario,0) as varchar(100)) = @Usuario
) > 0
    print 'Validado'
else
    print 'Error en credenciales'
go

Ya tenemos todo el código necesario vamos a probarlo con las siguientes sentencias:

Agregamos un usuario

-- Agrego un usuario de prueba
exec dbo.AgregarUsuario 'Mariano', 'PassW0rd';
go

Probamos con una contraseña válida y vemos que nos imprime el cartel de validado. Luego probamos con una contraseña errónea y vemos que nos imprime el cartel de credenciales erróneas.

-- Probamos con la clave correcta
exec dbo.ValidarUsuario 'Mariano', 'PassW0rd';
GO

-- Probamos con la clave incorrecta
exec dbo.ValidarUsuario 'Mariano', 'otra password';
go

Para eliminar todo usamos el siguiente código

-- Borramos todo
use master;
drop database Prueba;
go

Conclusión

Vemos que se puede validar las credenciales, mediante el usuario y la contraseña de una manera eficiente con la funciones de cifrado y descifrado del SQL Server sin almacenar siquiera la contraseña cifrada lo que aumente la seguridad notablemente en los casos que queremos usar un mecanismo propietario.

Tags: ,

Artículos

Powered by SQL Total Consulting


View Jose Mariano Alvarez's profile on LinkedIn

 Add to Technorati Favorites 

Calendar

<<  junio 2017  >>
lumamijuvido
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

View posts in large calendar

Locations of visitors to this page

Widget Twitter not found.

Root element is missing.X


Valid XHTML 1.0 Transitional

Valid CSS!