Pregunta

Tengo una ventana de inicio de sesión que obtiene el nombre de usuario y la contraseña del usuario y me gustaría saber la mejor manera de manejar la contraseña. El nombre de usuario es solo un cuadro de texto normal, pero la contraseña es un cuadro de contraseña. PASO el nombre de usuario directamente al Modelo ViewModel, pero solo establece una propiedad SecureString en el Modelo ViewModel una vez que se hace clic en el botón de inicio de sesión usando el código-behind. Después de que se establece la contraseña Securestring, quiero validar.

Estoy escribiendo el loginbox ahora, pero aún no tengo el modelo completamente resuelto. ¿Cómo debo almacenar la contraseña en SQL Server? ¿Acabo de escribir el contenido de SecureString a SQL y luego trato de compararlo cuando el usuario intente iniciar sesión?

¿Fue útil?

Solución

Nunca debe almacenar una contraseña, ni siquiera encriptado ...

Simplemente almacene un hash de la contraseña (que evita que la paseta se recupere siempre que el hashing se implemente de manera segura) y para la validación de la contraseña suministrada por el usuario de la misma manera y compare los resultados ...

Hay estándares para hacerlo:

El estándar anterior hace que sea difícil usar tablas de arco iris, etc. porque hace que el cálculo sea muy costoso, ya que usa varias rondas además de una sal ... por lo tanto, el hashing es, por ejemplo, 1000 veces más lento (con 1000 rondas), pero esto es exactamente lo que Usted desea: el atacante deberá hacer el mismo cálculo y, por lo tanto, necesitará 1000 veces el poder o tiempo de precisión para lograr el objetivo por fuerza bruta ...

Puede almacenar el resultado como Varbinary directamente o como Varchar después de Base64 o Hex-codificando los bytes ... Deberá almacenar la sal junto con ella (que no es un riesgo de seguridad siempre que cada contraseña obtenga su propia criptográfica distinta criptográfica Asegure sal aleatorio generado).

Otros consejos

En mi concierto anterior almacenamos la contraseña como un valor de hash/cifrado/salado (usando MD5 en ese momento) como VARBINARY(32). Para comparar la contraseña más adelante, en lugar de intentar descifrar la contraseña, compararíamos el valor cifrado + salado que almacenamos con el valor cifrado + salado de la contraseña que se intenta. Si coincidían, entraron, si no coincidían, no entraron.

El trabajo de hash se realizó en el nivel medio (tanto para guardar la contraseña inicialmente como para comparar más tarde), pero un ejemplo basado en el servidor SQL (Para detenerse de @Yahia, esto no está destinado a decirle la forma más segura posible, solo estoy ilustrando la metodología con un ejemplo muy liviano. MD5 no es lo suficientemente fuerte para ti? Puede usar un algoritmo diferente y más complejo junto con técnicas de salación más avanzadas, especialmente si realiza el hash en el nivel de aplicación):

CREATE TABLE dbo.Users
(
    UserID INT IDENTITY(1,1) PRIMARY KEY,
    Username NVARCHAR(255) NOT NULL UNIQUE,
    PasswordHash VARBINARY(32) NOT NULL
);

Un procedimiento para crear un usuario (sin manejo de errores o prevención de Dupe, solo pseudo).

CREATE PROCEDURE dbo.User_Create
    @Username NVARCHAR(255),
    @Password NVARCHAR(16)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @salt NVARCHAR(16) = '$w0rdf1$h';

    INSERT dbo.Users(Username, Password)
        SELECT @Username, 
          CONVERT(VARBINARY(32), HASHBYTES('MD5', @Password + @Salt));
END
GO

Ahora un procedimiento para autenticar a un usuario.

CREATE PROCEDURE dbo.User_Authenticate
    @Username NVARCHAR(255),
    @Password NVARCHAR(16)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @salt NVARCHAR(16) = '$w0rdf1$h';

    IF EXISTS 
    (
      SELECT 1 FROM dbo.Users
        WHERE Username = @Username AND 
        PasswordHash = CONVERT(VARBINARY(32), HASHBYTES('MD5', @Password + @salt))
    )
    BEGIN
        PRINT 'Please, come on in!';
    END
    ELSE
    BEGIN
        PRINT 'You can keep knocking but you cannot come in.';
    END
END
GO

En realidad, probablemente realizaría el hash en la aplicación y pasaría los valores hash en AS Varbinary (32); esto hace que sea mucho más difícil "oler" la contraseña real de texto claro desde cualquier lugar. Y tal vez tampoco almacenarías la sal en texto plano con el código, pero recuperarla de otro lugar.

Esto definitivamente es más seguro que almacenar la contraseña sin cifrar, pero elimina la capacidad de recuperar la contraseña. Ganar-ganar en mi opinión.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top