Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

É seguro armazenar nomes de usuário e senhas no banco de dados?


O processo de armazenamento de senhas com uma medida básica de segurança é bastante simples:
  • Use as senhas com sal
  • Use um salt diferente para cada usuário/senha
  • Armazene o salt com a senha com hash no banco de dados
  • Quando eles tentarem fazer login, execute o que o PW tentou pelo mesmo método; compare o resultado.

Se eles inseriram a senha correta, os PWs com hash serão correspondentes. Hashing protege os usuários de ataques, bem como o zelador que passa por uma tela com os members mesa em exposição.

Criando Salt e Hashing o 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=="

Armazene o hash PW e o sal como parte do registro do usuário. O sal não é secreto, mas altere-o quando/se o usuário alterar sua senha.

Comparando uma tentativa de login

' 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

Se o usuário digitar o mesmo PW, deve resultar no mesmo hash, é simples assim. O código de hash não é tão complicado:

Métodos de 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
  • É tentador usar algo como um GUID (System.Guid.NewGuid.ToString ) como o salt, mas não é tão difícil usar o gerador de números aleatórios criptográficos.
  • Assim como a senha com hash, a string de retorno é mais longa devido à codificação.
  • Crie um novo salt sempre que o usuário alterar sua senha. Não use um sal global, ele anula o propósito.
  • Você também pode fazer o hash do PW várias vezes. Parte da chave é fazer com que demore muito tempo para tentar todas as várias combinações se/quando for atacado.
  • As funções são candidatas ideais para Shared / static membros da classe.

Observe também o artigo vinculado por Kenneth vale muito a pena ler.

Observe que o artigo menciona The salt should be stored in the user account table alongside the hash Isso não significa que você deve ter um Salt coluna no banco de dados. Você pode ver o seguinte sendo feito no artigo vinculado:
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

Para dividir o sal da senha com hash:
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

Você precisa das duas partes:depois de fazer o hash da tentativa de login no PW, compare-o com split(1) .