在SQL Server中存储,检索和验证密码(Securestring)
-
26-10-2019 - |
题
我有一个登录窗口,可以从用户那里获取用户名和密码,我想知道处理密码的最佳方法。用户名只是一个常规的文本框,但是密码是一个密码框。我将用户名直接传递到ViewModel,但仅在使用Code-Behind单击“登录”按钮后,仅在ViewModel上设置Securestring属性。设置密码Securestring后,我想验证。
我现在正在编写Loginbox,但是我还没有完全奏效的模型。我应该如何将密码存储在SQL Server中?我是否只将Securestring的内容写入SQL,然后在用户尝试登录时尝试进行比较?
解决方案
您绝不应该存储密码 - 甚至没有加密...
只需存储一个密码(只要以安全的方式实现哈希的范围,就可以防止pasword被检索),并且为了验证,您以相同的方式哈希提供了用户提供的密码并比较结果...
有这样做的标准:
- http://en.wikipedia.org/wiki/pbkdf2
- http://www.ietf.org/rfc/rfc2898.txt
- http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derverivebytes.aspx
上述标准使使用彩虹桌等很难使计算非常昂贵,因为除了使用盐之外,它使用了几轮...因此,哈希速度慢了1000倍(有1000发子弹),但这正是您想要 - 攻击者将需要进行相同的计算,因此需要用蛮力来实现进攻能力或时间的1000倍...
您可以将结果直接存储为varbinary,也可以在base64--或十六进制字节后将结果存储...固定生成的随机盐)。
其他提示
在我以前的演出中,我们将密码存储为哈希/加密/盐的值(当时使用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
);
创建用户的过程(没有错误处理或预防DUPE,只有伪)。
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) - 这使得从任何地方“嗅探”实际的清晰文本密码变得更加困难。而且,您也许也不会用代码将盐存储在纯文本中,而是从其他地方检索的。
这绝对比存储未加密的密码更安全,但是它可以删除检索密码的能力。我认为双赢。