将用户名和密码存储在数据库中是否安全? [英] Is it safe to store usernames and passwords in the database?
问题描述
我让人们在氏族中提交用户名和密码,我需要知道使用此代码将其提交到数据库中是否安全,或者在数据库中是否安全.
I have people submit a username and password for then in a clan and i need to know if it's safe to use this code to submit that into a database or if it's even safe in a database.
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 注入攻击.
I use Parameters to avoid SQL Injection Attacks.
----------------------------------------------------------------------------------
这不是重复的,因为它以不同的方式询问和存储密码.它使用 MD5 来散列密码.
This was not a duplicate as it was in a different way of asking and storing the password. It was using MD5 for hashing a password.
推荐答案
使用基本安全措施存储密码的过程相当简单:
The process for storing passwords with a basic measure of security is fairly simple:
- 用盐散列密码
- 为每个用户/密码使用不同的盐
- 将带有散列密码的盐存储在数据库中
- 当他们尝试登录时,通过相同的方法运行尝试的密码;比较结果.
如果他们输入了正确的密码,散列的密码将匹配.散列可以保护用户免受攻击,也可以防止管理员走过带有 members
表的屏幕.
If they entered the correct password, the hashed PWs will match. Hashing protects the users from attacks as well as the janitor walking by a screen with the members
table on display.
' 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 哈希和盐作为用户记录的一部分存储.盐不是秘密,而是在用户更改密码时/如果用户更改密码.
Store the PW hash and the salt as part of the user's record. The salt is not secret, but change it when/if the user changes their password.
' 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
如果用户输入相同的密码,应该得到相同的哈希值,就这么简单.散列代码并不那么复杂:
If the user enters the same PW, it should result in the same hash, it is as simple as that. The hashing code is not all that complicated:
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
) 之类的东西作为盐很诱人,但使用加密随机数生成器并不难. - 与散列密码一样,由于编码的原因,返回字符串更长.
- 每次用户更改密码时都会创建一个新盐.不要使用全局盐,它违背了目的.
- 您还可以多次散列 PW.部分关键是在受到攻击时要花很长时间尝试各种组合.
- 这些函数是
Shared
/static
类成员的理想选择. - It is tempting to use something like a GUID (
System.Guid.NewGuid.ToString
) as the salt, but it just isn't all that hard to use the cryptographic random number generator. - As with the hashed password, the return string is longer due to the encoding.
- Create a new salt every time the user changes their password. Don't use a global salt, it defeats the purpose.
- You can also hash the PW multiple times. Part of the key is to make it take a long time to try all various combinations if/when attacked.
- The functions are ideal candidates for
Shared
/static
class members.
另请注意,Kenneth 链接的文章非常值得一读.
Note also, the article linked to by Kenneth is well worth reading.
注意文章提到盐应该存储在散列旁边的用户帐户表
这并不意味着您必须在数据库中有一个 Salt
列.您可以在链接的文章中看到以下内容:
Note that the article mentions The salt should be stored in the user account table alongside the hash
This doesn't mean you must have a Salt
column in the DB. You can see the following being done in the linked article:
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)
进行比较.
You need both parts: after you hash the attempted log in PW, compare it to split(1)
.
这篇关于将用户名和密码存储在数据库中是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!