![]() |
Tipp 0196
|
Kennwort sicher speichern
|
 |
|
Autor/Einsender: Datum: |
|
Michael Werner 30.11.2009 |
|
Entwicklungsumgebung: |
|
VB.Net 2008 |
Framework: |
|
2.0 |
|
|
Wenn Sie ein sensibles Passwort über SaltPasswortHash verschlüsseln und in der Registry sicher
speichern, "versalzen" Sie jedem Hacker die Suppe: Ein Hash ist schon sehr schwer zurück zu verfolgen.
Aber ein SaltHash setzt noch einen oben drauf: Er wirkt wie ein Salzstreuer in den Augen des Angreifers.
|
Ein SaltHash hängt an das Kennwort eine Zufalls-Byte-Folge mit bestimmter Länge an, so dass
ein Entschlüsseln des Kennwortes praktisch unmöglich wird. Gespeichert wird der verschlüsselte SaltHash in der Registry mit Application.UserAppDataRegistry und
dessen Methode SetValue (Lesen mit GetValue). In der Registry werden die Daten unter folgendem Pfad abgelegt:
HKEY_CURRENT_USER\Software\[Firma]\[Anwendung]\[Version].
|
|
|
Imports System.Text.Encoding
Imports System.Security.Cryptography
Namespace zaack
Public Class SaltPasswordHashRegistry
#Region " Öffentliche Methoden "
''' <summary>
''' SaltPasswordHash erzeugen und in der Registry speichern
''' </summary>
''' <param name="pw">String</param>
''' <remarks> 1. öffentliche Methode (Public)</remarks>
Public Sub CreateSaltHashAndSaveInRegistry(ByVal pw As String)
'SaltPasswordHash erzeugen
Dim saltPwHash As Byte() = _
CreateSaltedPasswordHash(ASCII.GetBytes(pw), CreateSalt(2000))
'Speichern in der Registry
WriteToRegistry(saltPwHash)
End Sub
''' <summary>
''' Neues Passwort mit dem aus der Registry vergleichen
''' </summary>
''' <param name="pw">String</param>
''' <returns>Boolean</returns>
''' <remarks> 2. öffentliche Methode (Public)</remarks>
Public Function CheckNewPassword(ByVal pw As String) As Boolean
Return VerifyPassword(ASCII.GetBytes(pw), ReadFromRegistry)
End Function
#End Region
#Region " Registry "
''' <summary>
''' Speichern in der Registry
''' Application.UserAppDataRegistry
''' </summary>
''' <param name="SaltPwHash"></param>
''' <remarks></remarks>
Private Sub WriteToRegistry(ByVal SaltPwHash As Byte())
Dim name As String = "Password"
Try
Application.UserAppDataRegistry.SetValue(name, SaltPwHash)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
''' <summary>
''' Das gespeicherte SaltHashPasswort aus der Registry auslesen
''' </summary>
''' <returns>Byte()-Array oder Nothing</returns>
''' <remarks></remarks>
Private Function ReadFromRegistry() As Byte()
Dim name As String = "Password"
Try
If Not Application.UserAppDataRegistry.GetValue(name) _
Is Nothing Then
Return _
CType(Application.UserAppDataRegistry.GetValue(name), _
Byte())
Else
Return Nothing
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
Return Nothing
End Try
End Function
#End Region
#Region " SaltPasswordHash "
''' <summary>
''' Salz bestimmter Länge erzeugen
''' </summary>
''' <param name="SaltLength">Integer</param>
''' <returns>Salt As Byte()</returns>
''' <remarks></remarks>
Private Function CreateSalt(ByVal SaltLength As Integer) _
As Byte()
Dim Salt(SaltLength - 1) As Byte
'Kryptografischer Zufallszahlen-Generator
Dim csp As New RNGCryptoServiceProvider
csp.GetBytes(Salt)
Return Salt
End Function
''' <summary>
''' Hauptfunktion:
''' Das gesalzene Kennwort erzeugen (Hashwert + Salz)
''' </summary>
''' <param name="UnsaltedPassword">Kennwort als Byte()</param>
''' <param name="Salt">Salz-Byte()</param>
''' <returns>Byte()</returns>
''' <remarks>Kennwort als Byte()</remarks>
Private Function CreateSaltedPasswordHash(ByVal _
UnsaltedPassword As Byte(), ByVal Salt As Byte()) As Byte()
' Byte-Array-Größe bestimmen
Dim SaltedPassword(UnsaltedPassword.Length + _
Salt.Length - 1) As Byte
' Das ungesalzene Kennwort vorne einfügen
UnsaltedPassword.CopyTo(SaltedPassword, 0)
' Salz annfügen
Salt.CopyTo(SaltedPassword, UnsaltedPassword.Length)
' Den Hashwert für das gesalzene Kennwort erzeugen:
Dim SaltedPasswordHash As Byte() = CreateHash(SaltedPassword)
' Hashwert plus Salz, Byte-Array-Größe bestimmen
Dim SaltedPasswordHashPlusSalt(SaltedPasswordHash.Length + _
Salt.Length - 1) As Byte
' Hashwert einfügen
SaltedPasswordHash.CopyTo(SaltedPasswordHashPlusSalt, 0)
' Salzwert anhängen
Salt.CopyTo(SaltedPasswordHashPlusSalt, _
SaltedPasswordHash.Length)
' Gesalzenes Kennwort zurückgeben
Return SaltedPasswordHashPlusSalt
End Function
''' <summary>
''' Hash-Vergleich des gespeicherten mit zu prüfendem Kennwort
''' </summary>
''' <param name="UnsaltedPassword">Byte()</param>
''' <param name="StoredPassword">Byte()</param>
''' <returns>Boolean</returns>
''' <remarks></remarks>
Private Function VerifyPassword(ByVal UnsaltedPassword _
As Byte(), ByVal StoredPassword As Byte()) As Boolean
' Einen Hashwert vom zu prüfenden Kennwort erzeugen
Dim UnsaltedPasswordHash As Byte() = CreateHash(New Byte() {0})
' Die Salt-Länge bestimmen
Dim SaltLength As Integer = StoredPassword.Length - _
UnsaltedPasswordHash.Length
Dim SaltStart As Integer = StoredPassword.Length - SaltLength
Dim Salt(SaltLength - 1) As Byte
' Parameter bei Nothing False
If (UnsaltedPassword Is Nothing) OrElse _
StoredPassword Is Nothing) Then
Return False
End If
' Salzwert ermitteln
Dim i As Integer
For i = 0 To SaltLength - 1
Salt(i) = StoredPassword(SaltStart + i)
Next
' Hash für das gesalzene Kennwort erzeugen
Dim SaltedPasswordHash As Byte() = _
CreateSaltedPasswordHash(UnsaltedPassword, Salt)
' Den Hash mit dem gespeicherten Wert vergleichen
Return CompareByteArray(StoredPassword, SaltedPasswordHash)
End Function
''' <summary>
''' Hashwert (SHA1) aus einem übergebenen Bytearray erzeugen
''' </summary>
''' <param name="ByteArrayToHash">Byte()</param>
''' <returns>Byte()</returns>
''' <remarks></remarks>
Private Function CreateHash(ByVal ByteArrayToHash As Byte()) _
As Byte()
Dim sha As SHA1 = SHA1.Create()
Return sha.ComputeHash(ByteArrayToHash)
End Function
''' <summary>
''' Byte-Arrays vergleichen
''' </summary>
''' <param name="bArr1">Byte()</param>
''' <param name="bArr2">Byte()</param>
''' <returns>Boolean</returns>
''' <remarks></remarks>
Private Function CompareByteArray(ByVal bArr1 As Byte(), _
ByVal bArr2 As Byte()) As Boolean
' Gleiche Länge?
If (bArr1.Length <> bArr2.Length) Then
Return False
End If
' Iterieren und einzelne Arrayelemente vergleichen
Dim i As Integer
For i = 0 To bArr1.Length - 1
If bArr1(i) <> bArr2(i) Then
Return False
End If
Next
Return True
End Function
#End Region
End Class
End Namespace
| |
|
|
|
Windows-Version |
98/SE |
 |
|
ME |
 |
|
NT |
 |
|
2000 |
 |
|
XP |
 |
|
Vista |
 |
|
Win
7 |
 |
|
|
|
Download (42
kB)
|
Downloads bisher: [ 277 ]
|
|
|