【问题标题】:Is it safe to store usernames and passwords in the database?将用户名和密码存储在数据库中是否安全?
【发布时间】:2015-06-30 19:20:19
【问题描述】:

我让人们在部落中提交用户名和密码,我需要知道使用此代码将其提交到数据库是否安全,或者它在数据库中是否安全。

MySQLCon.Open()
Dim SQLADD As String = "INSERT INTO members(username,password) VALUES(@memberToAdd, @memberPassword)"
COMMAND = New MySqlCommand(SQLADD, MySQLCon)
COMMAND.Parameters.AddWithValue("@memberToAdd", memberToAdd.Text)
COMMAND.Parameters.AddWithValue("@memberPassword", membersPassword.Text)
COMMAND.ExecuteNonQuery()
MySQLCon.Close()
MySQLCon.Dispose()

我使用参数来避免 SQL 注入攻击。

------------------------------------------ --------------------------------------

这不是重复的,因为它以不同的方式询问和 存储密码。它使用 MD5 对密码进行哈希处理。

【问题讨论】:

  • 没有。存储密码的加盐哈希,而不是密码本身。非常大的公司的非散列密码被盗,所以你也可能发生这种情况。
  • @EricJ。我很困惑,从来没有听说过。
  • @EricJ。这对我没有帮助,只会让事情变得更加混乱。
  • 不太清楚它可以解释多简单...

标签: mysql .net vb.net


【解决方案1】:

存储具有基本安全措施的密码的过程相当简单:

  • 用盐对密码进行哈希处理
  • 为每个用户/密码使用不同的盐
  • 将带有哈希密码的盐存储在数据库中
  • 当他们尝试登录时,通过相同的方法运行尝试过的 PW;比较结果。

如果他们输入了正确的密码,散列的密码将匹配。散列可以保护用户免受攻击,也可以防止看门人走过显示有members 表格的屏幕。

创建盐和散列密码

' salt size is 32 (0-31
Private Const SaltSize As Integer = 31
...

Dim dbPW As String = TextBox1.Text
Dim dbSalt = CreateNewSalt(SaltSize)
' eg: "dsEGWpJpwfAOvdRZyUo9rA=="

Dim SaltedPWHash As String = GetSaltedHash(dbPW, dbSalt)
' examples:
' using SHA256: bbKN8wYYgoZmNaG3IsQ2DPS2ZPIOnenl6i5NwUmrGmo=
' using SHA512: 
' 0vqZWBIbOlyzL25l9iWk51CxxJTiEM6QUZEH1ph+/aNp+lk4Yf8NYv8RLhYtbqCNpOqO3y8BmM+0YWtbAhE+RA=="

将 PW 哈希和盐存储为用户记录的一部分。盐不是秘密,但当/如果用户更改密码时,请更改它。

比较登录尝试

' check if PW entered equals DB
Dim pwTry = TextBox2.Text
' hash the login attempt using the salt stored in the DB
Dim pwLogin = GetSaltedHash(pwTry, dbSalt)

' compare the hash of what they entered to whats in the DB:
If String.Compare(SaltedPWHash, pwLogin, False) = 0 Then
    ' okay!
    Console.Beep()
End If

如果用户输入同一个PW,结果应该是同一个hash,就这么简单。哈希码并没有那么复杂:

哈希方法

Private Function GetSaltedHash(pw As String, salt As String) As String
    Dim tmp As String = pw & salt

    ' or SHA512Managed
    Using hash As HashAlgorithm = New SHA256Managed()
        ' convert pw+salt to bytes:
        Dim saltyPW = Encoding.UTF8.GetBytes(tmp)
        ' hash the pw+salt bytes:
        Dim hBytes = hash.ComputeHash(saltyPW)
        ' return a B64 string so it can be saved as text 
        Return Convert.ToBase64String(hBytes)
    End Using

End Function

Private Function CreateNewSalt(size As Integer) As String
    ' use the crypto random number generator to create
    ' a new random salt 
    Using rng As New RNGCryptoServiceProvider
        ' dont allow very small salt
        Dim data(If(size < 7, 7, size)) As Byte
        ' fill the array
        rng.GetBytes(data)
        ' convert to B64 for saving as text
        Return Convert.ToBase64String(data)
    End Using
End Function
  • 使用 GUID (System.Guid.NewGuid.ToString) 之类的东西作为 salt 很诱人,但使用加密随机数生成器并不是那么难。
  • 与散列密码一样,由于编码,返回字符串更长。
  • 每次用户更改密码时创建一个新的盐。不要使用全局盐,它会破坏目的。
  • 您还可以多次散列 PW。部分关键是如果/当受到攻击时,尝试所有各种组合需要很长时间。
  • 这些函数非常适合 Shared / static 类成员。

另请注意,Kenneth 链接的文章非常值得一读。


请注意,the article 提到 The salt should be stored in the user account table alongside the hash 这并不意味着您必须在 DB 中有 Salt 列。您可以在链接的文章中看到以下内容:

Dim dbPW As String = TextBox1.Text
Dim dbSalt = CreateNewSalt(SaltSize)

' get the salted PW hash
Dim SaltedPWHash As String = GetSaltedHash(dbPW, dbSalt)
' store salt with the hash:
SaltedPWHash = String.Format("{0}:{1}", dbSalt, dbPW)
' salt + ":" + hashed PW now ready to store in the db

从散列密码中分离盐:

Dim SaltAndPWHash = rdr.Item("PWHash").ToString()

Dim split = SaltAndPWHash.Split(":"c)    ' split on ":"
Dim Salt = split(0)                      ' element(0) == salt
Dim StoredPWHash = split(1)              ' element(1) == hashed PW

这两个部分都需要:在 PW 中对尝试的日志进行哈希处理后,将其与 split(1) 进行比较。

【讨论】:

  • 这是一个可以接受的解决方案。如果你使用慢哈希方法来避免暴力攻击会更好,例如 PBKDF2 或 bcrypt
  • 是的,但我想让那些(比如 OP)以前从未听过“哈希”这个词的人尽可能简单
  • @Plutonix 我认为将盐存储在数据库中以供黑客查看使用了什么盐是不好的。
  • 这样做很正常。如果你做一些阅读,你会发现盐不需要保密。它不是第二个 PW,而是使某些攻击方法无效。参见this 例如(cmets 也是!)Also this you can't really keep the salt secret without using another secret
  • @Plutonix Console.beep 表示它是正确的密码还是错误的密码?什么更好? SHA512Managed 还是 SHA256Managed?
【解决方案2】:

不,您不应该在数据库中存储明文密码。

原因是,如果您的数据库被黑客入侵/窃取/泄露,您的所有用户密码都对黑客可用。

您应该执行以下操作: - 当用户注册时,将他的用户名连同密码的散列版本一起保存在数据库中 - 当用户尝试登录时,从数据库中获取用户名,对他提供的密码进行哈希处理,并将其与数据库中的哈希密码进行比较。

散列是一种将字符串转换为不同字符串的方法,您只能采用一种方式(也就是说,相同的输入将始终生成相同的输出,但如果您只有输出)。

要了解如何对字符串进行哈希处理,请阅读以下文章,其中包含不同语言的代码示例:https://crackstation.net/hashing-security.htm

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 2011-01-07
    • 1970-01-01
    相关资源
    最近更新 更多