문제

I have a login window that gets the username and password from the user and I would like to know the best way to handle the password. The username is just a regular textbox, but the password is a PasswordBox. I pass the username directly to the ViewModel, but only set a SecureString property on the ViewModel once the Login button is clicked using Code-Behind. After the Password SecureString is set I want to Validate.

I'm writing the LoginBox now, but I don't have the Model fully worked out yet. How should I store the password in SQL Server? Do I just write the contents of the SecureString to SQL and then try to compare it when the user tries to login?

도움이 되었습니까?

해결책

You should NEVER store a password - not even encrypted...

Just store a hash of the password (which prevents the pasword from being ever retrieved as long as the hashing is implemented in a secure manner) and for validation you hash the user supplied password the same way and compare the results...

There are standards to do so:

The above standard makes it hard to use rainbow tables etc. because it makes the calculation very expensive since it uses several rounds in addition to a salt... thus hashing is for example 1000 times slower (with 1000 rounds) but this is exactly what you want - the attacker will need to do the same calculation and thus will need 1000 times the precessing power or time to achieve the goal by brute force...

You can store the result either as VARBINARY directly or as VARCHAR after Base64- or HEX-encoding the bytes... you will need to store the salt along with it (which is no security risk as long as every password gets its own distinct cryptographically secure generated random salt).

다른 팁

At my previous gig we stored the password as a hashed/encrypted/salted value (using MD5 at the time) as VARBINARY(32). To compare the password later, rather than try to decrypt the password, we would compared the encrypted + salted value that we stored to the encrypted + salted value of the password being attempted. If they matched, they got in, if they didn't match, they didn't get in.

The hashing work was done in the middle tier (both for saving the password initially and for comparing later), but a SQL Server-based example (to stop @Yahia's grumbling, this is not meant to tell you the most secure way possible, I am just illustrating the methodology with a very lightweight example. MD5 not strong enough for you? You can use a different and more complex algorithm along with more advanced salting techniques, especially if you perform the hashing in the application tier):

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

A procedure to create a user (no error handling or dupe prevention, just 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

Now a procedure to authenticate a user.

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

In reality you would likely perform the hashing within the application, and pass the hash values in as VARBINARY(32) - this makes it much harder to "sniff" the actual clear-text password from anywhere. And you maybe wouldn't store the salt in plain text with the code either, but retrieve it from elsewhere.

This is definitely more secure than storing the password unencrypted, but it removes the ability to ever retrieve the password. Win-win in my opinion.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top