3

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()

I use Parameters to avoid SQL Injection Attacks.

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

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.

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
AfterShotzZHD
  • 311
  • 2
  • 4
  • 15

2 Answers2

10

The process for storing passwords with a basic measure of security is fairly simple:

  • Hash the passwords with salt
  • Use a different salt for each user/password
  • Store the salt with the hashed password in the DB
  • When they try to log in, run what the attempted PW thru the same method; compare the result.

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.

Creating Salt and Hashing the PW

' 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=="

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.

Comparing a Login attempt

' 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:

Hash Methods

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
  • 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.

Note also, the article linked to by Kenneth is well worth reading.


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

To split the salt from the hashed password:

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

You need both parts: after you hash the attempted log in PW, compare it to split(1).

Community
  • 1
  • 1
Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
  • 1
    That is an acceptable solution. It would be even better if you use used a slow hash method to avoid brute force attacks, such as PBKDF2 or bcrypt – Kenneth Jun 30 '15 at 23:44
  • yes, but I wanted to keep it as simple as possible for those who (like the OP) have never heard the word "hash" before – Ňɏssa Pøngjǣrdenlarp Jun 30 '15 at 23:51
  • 1
    @Plutonix i don't think its good to store the salt in the DB for hackers to see what salt was used. – AfterShotzZHD Jul 01 '15 at 02:24
  • It is quite normal to do so. If you do some reading you'll see that salt does not need to be secret. It is not a second PW but invalidates certain attack methods. See [this](http://stackoverflow.com/a/5252990/1070452) for example (comments too!) [Also this](http://stackoverflow.com/q/213380/1070452) `you can't really keep the salt secret without using another secret` – Ňɏssa Pøngjǣrdenlarp Jul 01 '15 at 12:36
  • @Plutonix Would the Console.beep represent it is the correct password or wrong password? whats better? SHA512Managed or SHA256Managed? – AfterShotzZHD Jul 01 '15 at 19:10
  • The Beep means they match, if they do not, [`String.Compare()`](https://msdn.microsoft.com/en-us/library/84787k22(v=vs.110).aspx) returns non zero. `SHA256Managed` will return a longer hash as the comment in the first block shows – Ňɏssa Pøngjǣrdenlarp Jul 01 '15 at 19:17
1

No, you should not store clear text password in your database.

The reason is that if your database gets hacked/stolen/compromised all your user's password are available to the hacker.

What you should do instead is the following: - When a user signs up, save his username in the database, together with a hashed version of the password - When a user tries to login, get the username from the database, hash the password he provided and compare it with the hashed password in the database.

Hashing is a way of transforming a string into a different string, where you can only go one way (that is, the same input will always generate the same output, but you can never get the input back if you only have the output).

To find out how to hash a string, please read the following article, it has code samples for different languages: https://crackstation.net/hashing-security.htm

Kenneth
  • 28,294
  • 6
  • 61
  • 84