username and password verification vb.net - vb.net

My program below checks if the userName and the password is in the database( written in visual basic and uses Access database). The program works however, when I type in the userName or password in a different case it still works. For example, if my database has the userName as "john" and the password as "johnspassword", my program accepts the username as "JOHN" and password as "JOHNSPASSWORD".
how do i resolve this problem?
Dim con As New OleDbConnection("Provider=Microsoft.jet.oledb.4.0;data source=C:\Users\jacob\Desktop\MS Office\project.mdb")
Dim cmd As OleDbCommand = New OleDbCommand("SELECT * FROM tblUsers WHERE UserID = '" & txtUserName_Field.Text & "' AND userPassword = '" & txtUserPassword_Field.Text & "' ", con)
con.Open()
Dim sdr As OleDbDataReader = cmd.ExecuteReader()
'If the record can be queried, it means passing verification, then open another form.
Dim empty =
Me.Controls.OfType(Of TextBox)().Where(Function(txt) txt.Text.Length = 0)
If empty.Any Then
MessageBox.Show(String.Format("Please fill in all the fields required"))
Else
If (sdr.Read() = True) Then
MessageBox.Show("The is valid!")
Form4.Show()
Me.Hide()
Else
MessageBox.Show("Invalid name or password!")
End If
End If
con.Close()
End Sub

If you use a hash of the password instead then you solve two problems you have:
You should not store passwords as plain text
A hash will make the password case-sensitive
The Rfc2898DeriveBytes Class is suitable for creating the hash; you'll need a randomly-generated salt stored in the database for each user too.
There are many sites, e.g., Salted Password Hashing - Doing it Right, with explanations of why salting and hashing are desirable.
You will still have to decide if you need the username to be case-sensitive.
EDIT
It appears that Access doesn't have an efficient (i.e. sargable) way to do a case-sensitive comparison, so you can simply get the username from the database and check it in your program, something like this:
Option Infer On
Option Strict On
Imports System.Data.OleDb
Imports System.Security.Cryptography
Public Class SomeClass
'TODO: decide on the sizes for the salt and hash
'TODO: create binary fields in the database of appropriate sizes
'TODO: consider storing the number of iterations in the database
Const SALTLENGTH As Integer = 8
Const HASHLENGTH As Integer = 16
Const PBKDF2ITERATIONS As Integer = 20000
Friend Function PBKDF2Hash(password As String, salt As Byte(), iterations As Integer, hashSize As Integer) As Byte()
Dim hasher As New Rfc2898DeriveBytes(password, salt, iterations)
Return hasher.GetBytes(hashSize)
End Function
Function IsLoginValid(username As String, password As String) As Boolean
Dim salt(SALTLENGTH - 1) As Byte
Dim hashedPassword(HASHLENGTH - 1) As Byte
Dim usernameIsValid = False
Dim csb As New OleDbConnectionStringBuilder With {
.Provider = "Microsoft.jet.oledb.4.0",
.DataSource = "C:\Users\jacob\Desktop\MS Office\project.mdb"
}
Using conn As New OleDbConnection(csb.ConnectionString)
'TODO: use the actual column names
Using cmd As New OleDbCommand("SELECT UserID, salt, password FROM tblUsers WHERE UserID = ?", conn)
'TODO: use type of column as specified in the database
cmd.Parameters.Add(New OleDbParameter With {.OleDbType = OleDbType.VarWChar, .Value = username})
conn.Open()
Dim rdr = cmd.ExecuteReader()
If rdr.HasRows Then
rdr.Read()
If String.Compare(rdr.GetString(0), username, StringComparison.Ordinal) = 0 Then
rdr.GetBytes(1, 0, salt, 0, SALTLENGTH)
rdr.GetBytes(2, 0, hashedPassword, 0, HASHLENGTH)
usernameIsValid = True
End If
End If
conn.Close()
End Using
End Using
Dim expectedHash = PBKDF2Hash(password, salt, PBKDF2ITERATIONS, HASHLENGTH)
If usernameIsValid AndAlso hashedPassword.SequenceEqual(expectedHash) Then
Return True
End If
Return False
End Function
Private Sub bnLogin_Click(sender As Object, e As EventArgs) Handles bnLogin.Click
Dim username = txtUserName_Field.Text
Dim password = txtUserPassword_Field.Text
If username.Length = 0 OrElse password.Length = 0 Then
MessageBox.Show("Please fill in all the fields required.")
Exit Sub
End If
If IsLoginValid(username, password) Then
' user has supplied valid credentials
Else
MessageBox.Show("Invalid username or password.")
End If
End Sub
End Class
Of course, you still have to create the code to put the appropriate data in the database when the user is registered.

Related

Failed to convert parameter value from a List`1 to a String

I am getting the error message:
"Failed to convert parameter value from a List`1 to a String"
and I am not sure how to correct the issue. It happens when I attempt to save a cleaningList to a Cleaner object in a database.
I am very new to visual basic and appreciate any feedback to help make this program work.
Public Class FrmMain
Dim currentRoom As String
Dim lastId As Integer
Dim cleaners As New BindingList(Of Cleaner)
'new instance of cleaner and storing it in a reference variable
Dim currentCleaner As New Cleaner()
'-------------Functions----------------
Private Function connectWithDb() As SqlConnection
'create a connection string
Dim connectionString As String = "Server=(LocalDB)\MSSQLLocalDB;Integrated Security=true;AttachDbFileName=C:\Users\Julia\Desktop\JklimeckFinalProject\JklimeckFinalProject\cleanerLists.mdf;"
'create connection object and tell it how to connect using connectionString
Dim dbConnection As New SqlConnection(connectionString)
'open the connection
dbConnection.Open()
'return the connection
Return dbConnection
End Function
'function to change the list to a string seperated by commas
Public Function changeToString() As String
'turn the list of strings into a single string for the database
'trim the leading white space so it won't show up when the list is
'converted back later
currentCleaner.CleaningList = LTrim(String.Join(",", currentCleaner.ItemList.ToArray()))
Return currentCleaner.CleaningList
End Function
'public function to get index of items that are selected
Public Function GetAllItems(index As Integer) As CheckState
End Function
'function to generate a cleaning list
Public Function getCleanList() As List(Of String)
'if statement to display tasks in lbxTasks
Dim indexChecked As Integer
'variable to hold the tasks that are listed depending on the room
'selected ' for current cleaner
Dim itemList As New List(Of String)
'determine the room and create the list of tasks depending on the checked boxes
If currentRoom = "Living Room" Then
itemList.AddRange(currentCleaner.LivRoomTasks)
ElseIf currentRoom = "Kitchen" Then
itemList.AddRange(currentCleaner.KitchenTasks)
ElseIf currentRoom = "Bathroom" Then
itemList.AddRange(currentCleaner.BathroomTasks)
ElseIf currentRoom = "Bedroom" Then
itemList.AddRange(currentCleaner.BedroomTasks)
ElseIf currentRoom = "Dining Room" Then
itemList.AddRange(currentCleaner.DinRoomTasks)
ElseIf currentRoom = "Office" Then
itemList.AddRange(currentCleaner.OfficeTasks)
ElseIf currentRoom = "Laundry Room" Then
itemList.AddRange(currentCleaner.LauRoomTasks)
ElseIf currentRoom = "General" Then
itemList.AddRange(currentCleaner.GeneralTasks)
End If
For Each indexChecked In cbxRoomItems.CheckedIndices
lbxTasks.Items.Add(itemList.Item(indexChecked).ToString)
Next
Return itemList
End Function
'function to seperated the string version of the list
Public Function changeToList() As List(Of String)
'change the comma separated sting back to a list by spliting it at the commas
lbxTasks.Items.AddRange(currentCleaner.CleaningList.Split(New Char() {","c}))
Return currentCleaner.ItemList
End Function
Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles Me.Load
'when the application loads, show list of cleaners and display by name
lbxNames.DataSource = cleaners
lbxNames.DisplayMember = "Name"
Dim dbConnection As SqlConnection = connectWithDb()
'string of sql
Dim sqlString As String = "SELECT * FROM Cleaner"
'command object pass in what to run and the object
Dim selectCommand As New SqlCommand(sqlString, dbConnection)
'place in a try catch block to keep exceptions from crashing application
Try
'variable to hold the sqlDataReader object
Dim reader As SqlDataReader = selectCommand.ExecuteReader()
If reader.HasRows Then
'read is boolean
While reader.Read
'call the sub
populateCleaners(reader)
End While
End If
reader.Close()
'determine the highest ID number in the database
'and store it in a class level variable so we can access it
'where ever it is needed
Dim identSql As String = "SELECT IDENT_CURRENT('Cleaner') as lastID"
Dim identCom As New SqlCommand(identSql, dbConnection)
Dim identReader As SqlDataReader = identCom.ExecuteReader
If identReader.HasRows Then
identReader.Read()
lastId = CInt(identReader.Item("lastId"))
End If
Catch ex As Exception
End Try
'close and dispose the connection to the db
dbConnection.Close()
dbConnection.Dispose()
End Sub
'Sub to populate the database with a new character
Private Sub populateCleaners(reader As SqlDataReader)
Dim dbCleaner As New Cleaner()
changeToString()
'get info from reader and store into new object
dbCleaner.Id = CInt(reader.Item("Id"))
dbCleaner.Name = reader.Item("Name").ToString
dbCleaner.CleaningList = reader.Item("CleaningList").ToString
'add to binding list
cleaners.Add(dbCleaner)
End Sub
'----------------Butttons------------------
'add to list button
Private Sub btnClean_Click(sender As Object, e As EventArgs) Handles btnClean.Click
'label to show the correct list is being displayed
lblCurrentCleaner.Text = currentCleaner.Name
getCleanList()
End Sub
'save cleaning list
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim newCleaner As New Cleaner()
'referencing object and assigning it to the Name property for the new cleaner
newCleaner.Name = txtName.Text
'exception if the user does not enter a name
Try
newCleaner.Name = txtName.Text
Catch ex As Exception
MessageBox.Show("a cleaner has no name")
End Try
For ctr = 0 To lbxTasks.Items.Count - 1
newCleaner.ItemList.Add(lbxTasks.Items(ctr).ToString)
'change this list to a string
changeToString()
Next
newCleaner.CleaningList = changeToString()
lbxTasks.Items.Clear()
cleaners.Add(newCleaner)
currentCleaner = newCleaner
'update a cleaning list if the Id is already in the database, or create a new object
Dim dbConnection As SqlConnection = connectWithDb()
Dim sqlString As String
If currentCleaner.Id > 0 Then
sqlString = "UPDATE Cleaner SET Name = #name, CleaningList = #cleaningList WHERE Id = #id"
Else
sqlString = "INSERT INTO Cleaner (Name, CleaningList) VALUES(#name, #cleaningList)"
'increment the last Id and save that id number to the new entry in the db
lastId += 1
currentCleaner.Id = lastId
End If
Dim com As New SqlCommand(sqlString, dbConnection)
'set the values of current cleaner in the database
com.Parameters.Add("#id", SqlDbType.Int).Value = currentCleaner.Id
com.Parameters.Add("#name", SqlDbType.VarChar).Value = currentCleaner.Name
com.Parameters.Add("#cleaningList", SqlDbType.NVarChar).Value = currentCleaner.ItemList
Try
Dim result = com.ExecuteNonQuery()
MessageBox.Show(result.ToString)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
I have a Cleaner class that stores the public properties.
In the program the user clicks on different buttons that populate a checklistbox with different items found in that room, by selecting the items and clicking btnClean it populates a listbox with a list of tasks associated with the items the user selected. My problem seems to be centered around that list; it is stored in a list(of String), but I made a function to turn that list into a single string separated by commas so it can be stored in a database and another function to separated that list so it can be displayed back in the listbox when the user's name is selected.
I am not sure where it is I am going wrong.
The exception is being thrown in:
'save cleaning list
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim newCleaner As New Cleaner()
'referencing object and assigning it to the Name property for the new cleaner
newCleaner.Name = txtName.Text
'exception if the user does not enter a name
Try
newCleaner.Name = txtName.Text
Catch ex As Exception
MessageBox.Show("a cleaner has no name")
End Try
For ctr = 0 To lbxTasks.Items.Count - 1
newCleaner.ItemList.Add(lbxTasks.Items(ctr).ToString)
'change this list to a string
changeToString()
Next
lbxTasks.Items.Clear()
cleaners.Add(newCleaner)
currentCleaner = newCleaner
'update a cleaning list if the Id is already in the database, or create a new object
Dim dbConnection As SqlConnection = connectWithDb()
Dim sqlString As String
If currentCleaner.Id > 0 Then
sqlString = "UPDATE Cleaner SET Name = #name, CleaningList = #cleaningList WHERE Id = #id"
Else
sqlString = "INSERT INTO Cleaner (Name, CleaningList) VALUES(#name, #cleaningList)"
'increment the last Id and save that id number to the new entry in the db
lastId += 1
currentCleaner.Id = lastId
End If
Dim com As New SqlCommand(sqlString, dbConnection)
com.Parameters.Add("#name", SqlDbType.VarChar).Value = currentCleaner.Name
com.Parameters.Add("#cleaningList", SqlDbType.NVarChar).Value = currentCleaner.ItemList
Try
Dim result = com.ExecuteNonQuery()
MessageBox.Show(result.ToString)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Again thank you for any suggestions/help!

encrypting/decrypting a password stored on a compact database

My project contains 2 forms, one to register users and one to login. I am using a compact local database to store the passwords. I wrote a function to encrypt the password when the user registers. I then wrote another to decrypt the same password when the user logs in.
The first part, encryption, works just fine. The user registers, and I can see the password encrypted on the database. However, when I try to log in, the password is not being decrypted. Here are my Functions.
Module EncryptionModule
Public Function base64Encode(ByVal sData As String) As String
Try
Dim encData_Byte As Byte() = New Byte(sData.Length - 1) {}
encData_Byte = System.Text.Encoding.UTF8.GetBytes(sData)
Dim encodedData As String = Convert.ToBase64String(encData_Byte)
Return (encodedData)
Catch ex As Exception
Throw (New Exception("Error is base64Encode" & ex.Message))
End Try
End Function
Public Function base64Decode(ByVal sData As String) As String
Dim encoder As New System.Text.UTF8Encoding()
Dim utf8Decode As System.Text.Decoder = encoder.GetDecoder()
Dim todecode_byte As Byte() = Convert.FromBase64String(sData)
Dim charCount As Integer = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length)
Dim decoded_char As Char() = New Char(charCount - 1) {}
utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0)
Dim result As String = New [String](decoded_char)
Return result
End Function
End Module
This is the routine to register a user and encrypting the password:
Private Sub btnRegister_Click(sender As Object, e As EventArgs) Handles btnRegister.Click
'If the username is taken or used on the
'database, then create account
If MasterTableAdapter.CheckUserName(txtUserName.Text) = Nothing Then
Dim pwd As String = base64Encode(Trim(txtConfirmPassword.Text))
MasterTableAdapter.CreateAccount(txtFName.Text, txtLName.Text, txtUserName.Text, pwd, int1)
MsgBox("An account has been created for: " & vbNewLine & _
"Employee: " & txtFName.Text & " " & txtLName.Text & vbNewLine & _
"User Name: " & txtUserName.Text & vbNewLine & _
"Access Level: " & strAccessLevel)
Me.Close()
Else
MessageBox.Show("The username is in use. Please select another username.", "Authentication Error", MessageBoxButtons.OK, _
MessageBoxIcon.Error)
End If
End Sub
Here is the routine to log in and decrypt the password from the Login Form:
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
Dim pwd As String = base64Decode(Trim(txtPassword.Text))
If Not MasterTableAdapter.Login(txtUserName.Text, pwd) = Nothing Then
'frmWelcomePage.Show()
MsgBox("SUCCESS")
Else
'If no match, display error, clear text boxes and send focus back to the username text box.
MessageBox.Show("Username or password do not match", "Authentication Failure", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
txtPassword.Text = Nothing
txtUserName.Text = Nothing
txtUserName.Focus()
End If
End if
End Sub
I am new to the whole encryption arena so I don't know what I am doing wrong here.
You shouldn't decrypyt the password.
When the user creates a password, you should generate a hash (ie: a value from which the password can not be reconstructed)
When the user attempts to login, you should compare the hash value of the given password with the stored hash.
First, Base64 encoding is not encryption. Many people can look at a B64 string and know what to do to unscramble it. You should look into hash techniques as podiluska suggested.
That said, since your Decode method cant unscramble what you encode, it means you have an error in one or the other. Simple encoding for what you are doing can be done:
Dim s As String = "MySecretPassword"
' convert to byte array
Dim bArry() As Byte = System.Text.Encoding.UTF8.GetBytes(s)
' convert bytes to Base64:
Dim sb64 As String = System.Convert.ToBase64String(barry)
To decode is just the reverse:
' Base64 -> Byte Array
Dim bOut() As Byte = System.Convert.FromBase64String(sb64)
' Byte Arry -> clear text
Dim sOut As String = System.Text.Encoding.UTF8.GetString(bOut)

When combo box data selected, fill out textbox with data from Database

I am working on an application and I have a question, I have a Combo box that is bound to a table in my databse, when data is selected in the combo box I would like 'textbox 1' and 'textbox2' to be automatically filled out with data from the table, is this possible? so say for instance when I select 'Richard' on the combo box, 'Richards' 'Address1' and 'Postcode' are filled out in text boxes. I have a sample code that does this but it only seems to work with Int32, see insterted below.
Public Class Form1
Private Sub cmdGetByIdentifier_Click(sender As Object, e As EventArgs) Handles cmdGetByIdentifier.Click
If Not String.IsNullOrWhiteSpace(txtIdentifier1.Text) Then
Dim Identifier As Int32 = 0
If Int32.TryParse(txtIdentifier1.Text, Identifier) Then
txtCompanyName1.Text = GetCustomerNameByIdentifier(Identifier)
Else
MessageBox.Show("'" & txtIdentifier1.Text & "' is not a valid integer.")
End If
Else
MessageBox.Show("Must enter an identifier to get a company name.")
End If
End Sub
Private Sub cmdGetCustomer_Click(sender As Object, e As EventArgs) Handles cmdGetCustomer.Click
If Not String.IsNullOrWhiteSpace(txtIdentifier2.Text) Then
Dim Identifier As Int32 = 0
If Int32.TryParse(txtIdentifier2.Text, Identifier) Then
Dim Cust As Customer = GetCustomer(Identifier)
txtCompanyName2.Text = Cust.Name
txtContactName2.Text = Cust.ContactName
Else
MessageBox.Show("'" & txtIdentifier1.Text & "' is not a valid integer.")
End If
Else
MessageBox.Show("Must enter an identifier to get a company name.")
End If
End Sub
End Class
Module DatabaseOperations
Public Function GetCustomerNameByIdentifier(ByVal Identifier As Int32) As String
Dim CompanyName As String = ""
Dim Builder As New OleDb.OleDbConnectionStringBuilder With {.Provider = "Microsoft.ACE.OLEDB.12.0", .DataSource = IO.Path.Combine(Application.StartupPath, "Database1.accdb")}
Using cn As New OleDb.OleDbConnection With {.ConnectionString = Builder.ConnectionString}
Using cmd As New OleDb.OleDbCommand With {.Connection = cn}
cmd.CommandText = "SELECT CompanyName FROM Customer WHERE Identifier =#P1"
Dim NameParameter As New OleDb.OleDbParameter With {.DbType = DbType.Int32, .ParameterName = "P1", .Value = Identifier}
cmd.Parameters.Add(NameParameter)
cn.Open()
CompanyName = CStr(cmd.ExecuteScalar)
End Using
End Using
Return CompanyName
End Function
Public Function GetCustomer(ByVal Identifier As Int32) As Customer
Dim Customer As New Customer
Dim CompanyName As String = ""
Dim Builder As New OleDb.OleDbConnectionStringBuilder With {.Provider = "Microsoft.ACE.OLEDB.12.0", .DataSource = IO.Path.Combine(Application.StartupPath, "Database1.accdb")}
Using cn As New OleDb.OleDbConnection With {.ConnectionString = Builder.ConnectionString}
Using cmd As New OleDb.OleDbCommand With {.Connection = cn}
cmd.CommandText = "SELECT Identifier, CompanyName,ContactName FROM Customer WHERE Identifier =#P1"
Dim NameParameter As New OleDb.OleDbParameter With {.DbType = DbType.Int32, .ParameterName = "P1", .Value = Identifier}
cmd.Parameters.Add(NameParameter)
cn.Open()
Dim Reader As OleDb.OleDbDataReader = cmd.ExecuteReader
If Reader.HasRows Then
Reader.Read()
Customer.Identifier = Identifier
Customer.Name = Reader.GetString(1)
Customer.ContactName = Reader.GetString(2)
End If
End Using
End Using
Return Customer
End Function
End Module
Public Class Customer
Public Property Identifier As Int32
Public Property Name As String
Public Property ContactName As String
Public Sub New()
End Sub
End Class
1.Refer Below Link To Fetch Data from Sql server
2.Create a Function Which Will Return your Data with ID as parameter
Dataadapter with dataset - sql sever
Not 100% sure about using Access but in theory what you would do is have a customer object
You would have a SQL Stored Procedure
Select * from Customers where id=#ID
...
Then a class
Public Class Customer
public property ID as Integer
Public property Name as string
public Property Surname as string
....
End Class
In your code where you access the data you would have something like
Public Function GetCustomerDetailsByID (byval CustomerID as Integer) As Customer ' Or whatever you want to return it as
Dim myCust as New Customer
' Code to access SQL
' Call your SQL procedure called GetCustByID(CustID)
With myCust
.Name = valueFromYourProcedure
End With
End Function
In your client app, you would then call the above, then assign the values to your controls i.e.
Dim SingleCustomer as Customer = GetCustomerDetailsByID(1) ' i.e. value form your dropdown
txtBoxName.Text = SingleCustomer.Name
Thats a very rough example and isnt fully complete but should give you some idea of how to go about this. Theres a lot of ways to do the above and everyone has their own way so you may need to do some extra research to be comfortable with it.
Hope this helps

How to save and retrieve a fingerprint template in phpmyadmin database, using VB

We are using digital persona for our biometrics. We can already save employee ID, employee name and assigned finger .Our problem is that we dont know how to save a fingerprint template to a database and retrieve it so that it can still be read and verified by the biometric scanner. The file extension is ".ftp" .
CODE:
Private Sub buttonRegister_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonRegister.Click
'Does user already exists
Dim bUserExists As Boolean = _Users.UserExists(New UserID(textBoxUserName.Text))
' first make sure the user is created if new user
If _ActiveUser Is Nothing Or Not bUserExists Then
' initialize with supplied user name
_ActiveUser = New User(textBoxUserName.Text)
Else
' update active user if not as originally selected
If bUserExists And Not listBoxUsers.SelectedItem.ToString() = textBoxUserName.Text Then
_ActiveUser = _Users(New UserID(textBoxUserName.Text))
End If
End If
' and check if the template already exists for the assigned finger
If _ActiveUser.TemplateExists(_AssignedFinger) Then
' show message indicating template already exists for selected finger
Dim diagResult As DialogResult = MessageBox.Show(Me, [String].Format("Oops!" + ControlChars.Cr + ControlChars.Lf + "{0} has a template enrolled to his/her {1} finger." + ControlChars.Cr + ControlChars.Lf + ControlChars.Cr + ControlChars.Lf + "Shall the old template be discarded?", _ActiveUser.ID.ToString(), _Fingers(_AssignedFinger)), "Template already assigned!", MessageBoxButtons.YesNo, MessageBoxIcon.Error)
' if user selected not to overwrite, then abort
If diagResult = Windows.Forms.DialogResult.No Then
Return
End If
End If
Try
' attempt to read the template
Dim templateOpened As New DPFP.Template(File.OpenRead(textBoxTemplateFilename.Text))
' run a template duplicate check
IdentifyTemplate(templateOpened)
' remove the old template if exists
If _ActiveUser.TemplateExists(_AssignedFinger) Then
' removed from assigned finger
_ActiveUser.RemoveTemplate(_AssignedFinger)
End If
' and assign it to the user as specified
_ActiveUser.AddTemplate(templateOpened, _AssignedFinger)
' update collection
If Not _Users.UserExists(_ActiveUser.ID) Then
' update list box
listBoxUsers.Items.Add(_ActiveUser.ID.ToString())
' add user it to the user collection
_Users.AddUser(_ActiveUser)
End If
' success
UpdateEventLog([String].Format("{0}: Template successfully assigned to {1} finger.", _ActiveUser.ID.ToString(), _AssignedFinger.ToString()))
' turn off groupbox
groupAddTemplate.Visible = False
listBoxUsers.SelectedItem = _ActiveUser.ID.ToString()
' sync gui
_syncUI()
' view user
_syncViewUser()
Catch Err As DPFP.Error.SDKException
' log message
UpdateEventLog(Err.ToString())
System.Diagnostics.Trace.WriteLine(Err.ToString())
Catch Err As System.IO.FileNotFoundException
' log message
UpdateEventLog("Template file not found or is inaccessible.")
System.Diagnostics.Trace.WriteLine(Err.ToString())
Catch Err As Exception
' log message
UpdateEventLog(Err.ToString())
System.Diagnostics.Trace.WriteLine(Err.ToString())
End Try
Using conn As New MySqlConnection("Server = localhost; Username= root; Password =; Database = vb")
Using cmd
With cmd
MsgBox("Connection Established")
.Connection = conn
.Parameters.Clear()
'Create Insert Query
.CommandText = "INSERT INTO employees(UserID, Name, Finger) VALUES (#iID, #iName, #iFinger)"
.Parameters.Add(New MySqlParameter("#iID", ID.Text))
.Parameters.Add(New MySqlParameter("#iName", textBoxUserName.Text))
.Parameters.Add(New MySqlParameter("#iFinger", comboBoxAssignedFinger.Text))
End With
Try
'Open Connection and Execute Query
conn.Open()
cmd.ExecuteNonQuery()
Catch ex As MySqlException
MsgBox(ex.Message.ToString())
End Try
End Using
End Using
i know that this is an old post but here are code blocks that might help...
IN SAVING I USED THIS
For Each template As DPFP.Template In Data.Templates
If Not template Is Nothing Then
cmd = New MySqlCommand("INSERT INTO employeefp " +
"SET No=#No, " +
"FP=#FP " +
" ", conn)
cmd.Parameters.Add(New MySqlParameter("#No", txtEmpNo.Text))
cmd.Parameters.Add(New MySqlParameter("#FP", template.Bytes))
cmd.ExecuteNonQuery()
End If
Next
IN VERIFYING FROM THE DB I USED THIS
WHEN FORM IS LOADED I FETCH ALL THE FINGER PRINTS
Dim cmd As New MySqlCommand("SELECT * FROM employeefp ", conn)
Dim rdr As MySqlDataReader = cmd.ExecuteReader()
While (rdr.Read())
Dim MemStream As IO.MemoryStream
Dim fpBytes As Byte()
fpBytes = rdr("FP")
MemStream = New IO.MemoryStream(fpBytes)
Dim templa8 As DPFP.Template = New DPFP.Template()
templa8.DeSerialize(MemStream)
Dim tmpObj As New AppData
tmpObj.No = rdr("No").ToString()
tmpObj.Template = templa8
FPList.Add(tmpObj)
End While
NOTE : Dim FPList As List(Of AppData) = New List(Of AppData) //you can find the definition of this in the SDK i just added Template (contains one print) aside from the existing Templates(contains many print)
COMPARE THE CURRENT SAMPLE FROM THE MACHINE
Sub OnComplete(ByVal Control As Object, ByVal FeatureSet As DPFP.FeatureSet, ByRef EventHandlerStatus As DPFP.Gui.EventHandlerStatus) Handles VerificationControl.OnComplete
Dim printFound As Boolean = False
VerifiedFPData = New AppData
Try
For Each FPData As AppData In FPList
Dim tmplateData As New DPFP.Template
tmplateData = FPData.Template
Dim compareTo As New DPFP.FeatureSet
compareTo = FeatureSet
Dim ver As New DPFP.Verification.Verification()
Dim res As New DPFP.Verification.Verification.Result()
If Not tmplateData Is Nothing Then
ver.Verify(FeatureSet, tmplateData, res)
If res.Verified Then
EventHandlerStatus = DPFP.Gui.EventHandlerStatus.Success
printFound = True
VerifiedFPData = FPData
Exit For ' success
End If
End If
Next
Catch ex As Exception
MessageBox.Show("verification error")
End Try
If printFound Then
//TO DO
Else
EventHandlerStatus = DPFP.Gui.EventHandlerStatus.Failure
// TODO
End If
End Sub
hope it helps someone :)
There are some missing codes from the answer above. The code of the class appdata is missing.These code is error without declaring first the tmpObj in the class AppData. Dim tmpObj As New AppData
tmpObj.No = rdr("No").ToString()
tmpObj.Template = templa8
FPList.Add(tmpObj)

Hashing gone wrong

I'm using the same function to hash values for comparison during login as I am to hash the passwords when users register:
Public Shared Function Compute(ByVal text As String, ByVal algorithm As String, Optional ByVal salt() As Byte = Nothing) As String
If salt Is Nothing Then
Dim saltSize As Integer = 8
salt = New Byte(saltSize - 1) {}
Dim rng As New RNGCryptoServiceProvider
rng.GetNonZeroBytes(salt)
End If
Dim textBytes As Byte() = Encoding.UTF8.GetBytes(text)
Dim saltedTextBytes() As Byte = New Byte(textBytes.Length + salt.Length - 1) {}
For i As Integer = 0 To textBytes.Length - 1
saltedTextBytes(i) = textBytes(i)
Next i
For i As Integer = 0 To salt.Length - 1
saltedTextBytes(textBytes.Length + i) = salt(i)
Next i
Dim hash As HashAlgorithm
If algorithm Is Nothing Then
algorithm = ""
End If
Select Case algorithm.ToUpper
Case "SHA1" : hash = New SHA1Managed
Case "SHA256" : hash = New SHA256Managed
Case "SHA384" : hash = New SHA384Managed
Case "SHA512" : hash = New SHA512Managed
Case Else : hash = New MD5CryptoServiceProvider
End Select
Dim hashBytes As Byte() = hash.ComputeHash(saltedTextBytes)
Dim saltedHash() As Byte = New Byte(hashBytes.Length + salt.Length - 1) {}
For i As Integer = 0 To hashBytes.Length - 1
saltedHash(i) = hashBytes(i)
Next i
For i As Integer = 0 To salt.Length - 1
saltedHash(hashBytes.Length + i) = salt(i)
Next i
Dim hashValue As String = Convert.ToBase64String(saltedHash)
Return Left(hashValue, 36)
End Function
My problem is that when I try to log in on an account whose password was hashed by this function, the hashed values don't match up. I think I'm skipping a step or something.
Here's the code for user account creation:
' The email address needs to be valid
Dim pattern As String = "^(?("")("".+?""#)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])#))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$"
Dim match As Match = Regex.Match(txtEmail.Text, pattern)
If match.Success Then
'Hash the user's password before entering it into the database.
Dim pass As String = Crypt.Compute(txtPass.Text, "SHA512", Nothing)
' Enter the information from the form into the database.
Dim sql As String = "INSERT INTO Users(Username, Password, EmailAddress) " & _
"VALUES(#User, #Pass, #Email)"
Dim cmd As New SqlCommand(sql, conn)
cmd.Parameters.AddWithValue("#User", txtName.Text)
cmd.Parameters.AddWithValue("#Pass", pass)
cmd.Parameters.AddWithValue("#Email", txtEmail.Text)
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
Else
lblError.Text = "Invalid email address. Please correct."
lblError.ForeColor = Drawing.Color.Red
End If
There are more checks that aren't included here that aren't relevant to my problem.
Here's my user login:
Dim pass As String = Crypt.Compute(txtPass.Text, "SHA512", Nothing)
Dim UserData As New DataSet
Dim UserAdapter As New SqlDataAdapter
UserAdapter.SelectCommand = New SqlCommand("SELECT * FROM Users " & _
"WHERE Username = #User AND Password = #Pass", conn)
UserAdapter.SelectCommand.Parameters.AddWithValue("#User", txtUser.Text)
UserAdapter.SelectCommand.Parameters.AddWithValue("#Pass", pass)
UserAdapter.Fill(UserData)
If UserData.Tables(0).Rows.Count <> 1 Then
lblError.Text = "Invalid username or password."
lblError.ForeColor = Drawing.Color.Red
Session("LoginAttempt") = CInt(Session("LoginAttempt")) + 1
Else
Session("LoggedIn") = True
Response.Redirect("Home.aspx")
End If
As far as I can see, there is no difference in the hashing I've done here.
Does anyone have any ideas?
When you creating an account by inserting into the table, you are using txtName.Text for the username, but when checking the credentials you are using txtUser.Text.
Why are you using a random salt? Doesn't the salt have to be the same for every encryption? I've pasted your code into a new project, and when I run the Compute method twice in a row for the same password, I get two different results... obviously that won't work. Try passing in a salt value instead of Nothing, and use the same salt for creating accounts and comparing login. Here's some sample code that works:
Dim thePass As String = "MyPassword"
Dim theSalt As String = "salt"
Dim pass As String = Compute(thePass, "SHA512", Encoding.UTF8.GetBytes(theSalt))
Console.WriteLine(pass)
Dim pass2 As String = Compute(thePass, "SHA512", Encoding.UTF8.GetBytes(theSalt))
Console.WriteLine(pass2) 'pass and pass2 are identical
Hope this helps!
Unless I'm missing it (not really familiar with the language), you don't store the salt anywhere.
You have to use the same salt you've used when creating the account for the verification.
On a side note: You can either generate a random salt for every user account or use a fixed salt for all accounts. Either method works. The first is theoretically more secure, but if the salt is long enough, both are fine for practical purposes.