【问题标题】:How to do password validation in sql server?如何在sql server中进行密码验证?
【发布时间】:2016-09-15 10:15:50
【问题描述】:

我在 sql server 中使用 aes_256 算法加密了我的密码字段。密码字段现在已加密。现在我想登录用户,验证过程应该在服务器上完成。 我为验证过程编写的代码是:

CREATE PROCEDURE Procedure_UserLogin
    @username varchar(50),
    @pwd varchar(50),
    @responseMessage INT OUTPUT
AS
BEGIN
    SET NOCOUNT ON

    DECLARE @userID INT

    IF EXISTS(SELECT TOP 1 username FROM userInfo WHERE username=@username)
    BEGIN
        open symmetric key key1
        decryption by certificate namecert
        SET @userID=(SELECT username FROM userInfo WHERE username=@username AND encryptedpwd=(ENCRYPTBYKEY(KEY_GUID('key1'),@pwd)))
        IF (@userID IS NULL)
            SET @responseMessage=0 /*INAVLID PASSWORD*/
        ELSE
            SET @responseMessage=1  /*VALID USERNAME AND PASSWORD*/
    END
    ELSE
        SET @responseMessage=2 /*INVALID USERNAME*/
END

但是响应总是0。请告诉我我在做什么错误?

【问题讨论】:

  • 不要加密密码。任何被加密的东西都可以被解密。对您的密码进行加盐和哈希处理,并将哈希存储在数据库中。当用户登录时,对密码进行加盐和哈希处理,并将生成的哈希值与数据库中的哈希值进行比较。
  • 您正在选择用户名 (varchar) 到 @userID (Int)。我很惊讶您没有收到转换错误。
  • @dbugger,我没有将我的加密密码带到客户端,而且我认为 aes_256 算法生成的结果类似于哈希和盐一起完成的结果。如果我错了,请纠正我。
  • @JoeC,即使我很惊讶我没有收到转换错误。无论如何,我已经完成了更正。谢谢
  • 不,大不相同。如果您的系统受到威胁,它会暴露您的用户密码。 darkreading.com/…

标签: sql sql-server validation encryption passwords


【解决方案1】:

可以/不应该将密码验证委托给数据库。密码应使用慢速算法(如 BCrypt、PBKDF2 或 SCrypt)散列,而数据库系统通常不支持这些算法。加盐是强制性的,会阻止您搜索特定的密码哈希。

所以不要加密密码,而是像这样实现它:

// Get password-hash by user id
SELECT hashedpwd FROM userInfo WHERE username=@username

// Verify the password within your application, which supports a safe algorithm
// like BCrypt, PBKDF2 or SCrypt.
// Take the salt from $existingHashFromDb or from a separate db-field.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

【讨论】:

    【解决方案2】:

    简短的回答是因为ENCRYPTBYKEY每次输出不同的结果,并且存储在表中的加密值是恒定的。

    尝试运行下面的脚本以查看它的实际效果。

    DECLARE @passphrase VARCHAR(50);
    SET @passphrase = 'UseYourHashLuke';
    
    OPEN SYMMETRIC KEY KEY1
    DECRYPTION BY CERTIFICATE namecert
    
    SELECT ENCRYPTBYKEY(KEY_GUID('KEY1'), @passphrase);
    
    CLOSE SYMMETRIC KEY1
    GO 10
    

    您应该看到 10 个不同的输出。但是,如果您针对 encryptedpwd 的表运行 SELECT 语句,则每次的输出都是相同的。这就是为什么即使输入正确,您的脚本也永远无法正确验证用户输入的原因。

    现在,基于此,您可能正在考虑更改此行

    encryptedpwd=(ENCRYPTBYKEY(KEY_GUID('key1'),@pwd))) 
    

    这样的,对吧?

    DECRYPTBYKEY(KEY_GUID('key1'),encryptedpwd)) = @pwd
    

    没那么快。原因是DECRYPTBYKEYENCRYPTBYKEY都返回VARBINARY(8000),但用户输入@pwdVARCHAR(50)。因此,如果不将输出转换为匹配输入的数据类型,它们将始终不同。

    CONVERT(VARCHAR,DECRYPTBYKEY(KEY_GUID('key1'),encryptedpwd))) = @pwd
    

    最后,CLOSE SYMMETRIC KEY 上的 BOL 说

    开放对称密钥绑定到会话而不是安全上下文。一个打开的密钥将继续可用,直到它被显式关闭或会话终止。

    因此,最好在末尾显式关闭键。

    CLOSE SYMMETRIC KEY KEY1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-23
      • 1970-01-01
      • 2020-10-27
      相关资源
      最近更新 更多