1

我有一个登录窗口,可以从用户那里获取用户名和密码,我想知道处理密码的最佳方法。用户名只是一个普通的文本框,但密码是一个密码框。我将用户名直接传递给 ViewModel,但仅在使用 Code-Behind 单击 Login 按钮后才在 ViewModel 上设置 SecureString 属性。设置密码 SecureString 后,我想验证。

我现在正在编写 LoginBox,但我还没有完全设计好模型。我应该如何将密码存储在 SQL Server 中?我是否只是将 SecureString 的内容写入 SQL,然后在用户尝试登录时尝试比较它?

4

2 回答 2

4

你不应该存储密码 - 甚至不加密......

只需存储密码的哈希值(只要哈希以安全的方式实现,就可以防止密码被检索到),并且为了验证,您以相同的方式哈希用户提供的密码并比较结果......

有这样做的标准:

上述标准使得使用彩虹表等变得困难,因为它使计算非常昂贵,因为它除了盐之外还使用了几轮......因此散列例如慢了 1000 倍(使用 1000 轮),但这正是你想要 - 攻击者将需要进行相同的计算,因此需要 1000 倍的进动功率或时间才能通过蛮力实现目标......

您可以将结果直接存储为 VARBINARY 或在对字节进行 Base64 或 HEX 编码后存储为 VARCHAR ......您需要将盐与它一起存储(只要每个密码都有自己独特的密码,这没有安全风险安全生成的随机盐)。

于 2011-09-05T17:03:16.347 回答
1

在我之前的演出中,我们将密码存储为哈希/加密/加盐值(当时使用 MD5)作为VARBINARY(32). 为了稍后比较密码,而不是尝试解密密码,我们会将我们存储的加密 + 加盐值与正在尝试的密码的加密 + 加盐值进行比较。如果他们匹配,他们进入,如果他们不匹配,他们没有进入。

散列工作是在中间层完成的(最初保存密码和稍后比较),但是一个基于 SQL Server 的示例(为了阻止@Yahia 的抱怨,这并不是要告诉你最安全的方法,我我只是用一个非常轻量级的例子来说明方法。MD5 对你来说不够强大吗?你可以使用不同的更复杂的算法以及更高级的加盐技术,特别是如果你在应用层执行散列):

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

创建用户的过程(没有错误处理或防止重复,只是伪的)。

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

现在是一个验证用户的过程。

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

实际上,您可能会在应用程序中执行散列,并将散列值作为 VARBINARY(32) 传递 - 这使得从任何地方“嗅探”实际的明文密码变得更加困难。而且您可能也不会将盐与代码一起以纯文本形式存储,而是从其他地方检索它。

这绝对比存储未加密的密码更安全,但它消除了检索密码的能力。在我看来是双赢的。

于 2011-09-05T16:55:35.833 回答