Hash with MD5 in VB.NET - vb.net

So, I got a bit of a problem here, I got a database, a login and a registration, all in different classes, now I need to hash the password in the database and read it out again when logging in, but I don't know how to handle this, I already searched a lot but couldn't find anything useful.
Here is my login class
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlServerCe
Public Class Login
Inherits System.Web.UI.Page
Private Sub LSend_Click(sender As Object, e As System.EventArgs) Handles LSend.Click
If Bibliothek.EntryExists(LNAME.Text, "Username") = False Then
LNAMELBL.Text = "Name oder Passwort Falsch."
Exit Sub
End If
If Bibliothek.EntryExists(LPW.Text, "Passwort") = False Then
LNAMELBL.Text = "Name oder Passwort Falsch."
Exit Sub
End If
Dim UserN As String = LNAME.Text
Session("Admin") = Bibliothek.GetValueBool(UserN, "IsAdmin")
Session("USERNA") = Bibliothek.GetValueBool(UserN, "Username")
Response.Redirect("/TSL/Home.aspx")
End Sub
Private Sub REG_Click(sender As Object, e As System.EventArgs) Handles REG.Click
Response.Redirect("/TSL/Registrierung.aspx")
End Sub
End Class

It is important to note that MD5 is no longer considered a good way to hash data you wish to protect. See wikipedia for a discussion of the vulnerabilities.
See this answer for hashing using SHA.
For passwords, you'd save the hash of the user's PW to the DB. Because it is one-way (you cannot easily get the original value back from the hash), this prevents someone like a janitor or customer service rep from being able to see the actual passwords in the database.
Imports System.Security.Cryptography
Imports System.Text
Shared Function GetHash(theInput As String) As String
Using hasher As MD5 = MD5.Create() ' create hash object
' Convert to byte array and get hash
Dim dbytes As Byte() =
hasher.ComputeHash(Encoding.UTF8.GetBytes(theInput))
' sb to create string from bytes
Dim sBuilder As New StringBuilder()
' convert byte data to hex string
For n As Integer = 0 To dbytes.Length - 1
sBuilder.Append(dbytes(n).ToString("X2"))
Next n
Return sBuilder.ToString()
End Using
End Function
Depending on how you want to save it, rather than a using StringBuilder to create a hex string, you can use Convert.ToBase64String():
Return Convert.ToBase64String(dbytes)
' MyWeakPassword hashed:
' to hex: DB28F1BE20A407398171295DD0D191E2
' to Base64: 2yjxviCkBzmBcSld0NGR4g==
Hashing should be done with salt. This is data added to the hash to make the result less predictable (there are dictionaries of the hashed results of common PW such as "password"; salt changes the outcome):
Shared Function GetHash(theInput As String, theSalt As String) As String
...
hasher.ComputeHash(Encoding.UTF8.GetBytes(theInput & theSalt))
Salt should be created using the Cryptographic random number generator as shown in the SHA Version. Convert the salt to text (hex or Base64) then combine with the PW to get the PW hash.
To check/compare a user's entry, simply hash the input and compare it to the hash stored in the database, using the same Salt (which means the Salt needs to be saved):
Shared Function CheckHash(hashedStr As String, newInput As String) As Boolean
' get the hash value of user input:
Dim newHash As String = GetHash(newInput & dbSalt)
' return comparison
Return String.Compare(newHash, hashedStr, InvariantCultureIgnoreCase)
End Function
As written, the GetHash function is intended to be used from something like a CryptoTools Class. Since it is Shared/Static the class need not be instanced:
thisHash = CryptoTools.GetHash(strToHash)
Note: Hashing is case sensitive, so foobar will result in a different hash than FooBar or FOOBAR. To create a case insensitive system, convert the original string (such as a password) to lowercase before you compute the MD5 hash value to be saved, and do the same for the value they later enter:
' ToLowerInvariant allows for foreign char sets
Dim str As String = PWTextBox.Text.ToLowerInvariant
If CheckHash(dbHashedValue, str) Then
' okie dokie
Else
' failed
End If

MD5 Convertion
Dim [source] As String = password_text_box.text
Using md5Hash As MD5 = MD5.Create()
Dim hash As String = GetMd5Hash(md5Hash, source)
2, Insert Name and hash into database
3, Validation
During login take MD5 of password again
run sql query
Select name,password from table where Login ='" & username & "' and
Password ='" & md5(user input pass) & "'
if dreader returns value , then valid login else invalid login

Private Function GetHash(strToHash As String) As String
Dim md5Obj As New System.Security.Cryptography.MD5CryptoServiceProvider
Dim bytesToHash() As Byte = System.Text.Encoding.ASCII.GetBytes(strToHash)
bytesToHash = md5Obj.ComputeHash(bytesToHash)
Dim strResult As New StringBuilder
For Each b As Byte In bytesToHash
strResult.Append(b.ToString("x2"))
Next
Return strResult.ToString
End Function

This would be my solution:
Public Sub _Enkripsi()
Dim _DES As New TripleDESCryptoServiceProvider()
Dim _HashMD5 As New MD5CryptoServiceProvider()
_DES.Key = _HashMD5.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(PasswordTextBox.Text))
_DES.Mode = CipherMode.ECB
Dim _DESEncrypt As ICryptoTransform = _DES.CreateEncryptor()
Dim _Buffer As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(PasswordTextBox.Text)
_Password = Convert.ToBase64String(_DESEncrypt.TransformFinalBlock(_Buffer, 0, _Buffer.Length))
End Sub

Convert String to MD5 Function for Visual Studio Basic 2022
Imports System.Security.Cryptography
Imports System.Text
Function CovertToMD5(retVal As String) As String
Using MD5 = System.Security.Cryptography.MD5.Create()
Return BitConverter.ToString(MD5.ComputeHash(Encoding.Default.GetBytes(retVal))).Replace("-", String.Empty)
End Using
End Function

Related

VB.NET Core 6, Hashing password in (Win form) using SHA512 - Visual Basic

I am trying to build an application where security and encryption are a high concern.
I am using Visual Studio 2022 and VB.NET 6.0 (I searched for 3 days now and couldn't find a suitable solution, all that I found is related to a different version of .NET and NOT Visual Studio 2022)
UPDATE: 16/5/2022
I updated my question to be more related to what I really need; which is hashing the password.
Thank you
This solution worked for me like charm:
Imports System.Security.Cryptography
Imports System.Text
Public Module hashing
Public Function PWDhash(ByVal password As String)
Using sha512Hash As SHA512 = SHA512.Create()
Return GetHash(sha512Hash, password)
End Using
End Function
Private Function GetHash(ByVal hashAlgorithm As HashAlgorithm, ByVal input As String) As String
' Convert the input string to a byte array and compute the hash.
Dim data As Byte() = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(input))
' Create a new Stringbuilder to collect the bytes
' and create a string.
Dim sBuilder As New StringBuilder()
' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
For i As Integer = 0 To data.Length - 1
sBuilder.Append(data(i).ToString("x2"))
Next
' Return the hexadecimal string.
Return sBuilder.ToString()
End Function
' Verify a hash against a string.
Public Function VerifyHash(hashAlgorithm As HashAlgorithm, input As String, hash As String) As Boolean
' Hash the input.
Dim hashOfInput As String = GetHash(hashAlgorithm, input)
' Create a StringComparer an compare the hashes.
Dim comparer As StringComparer = StringComparer.OrdinalIgnoreCase
Return comparer.Compare(hashOfInput, hash) = 0
End Function
End Module
This is how to hash:
Dim HashedPWD As String = PWDhash("password here")
This is how to verify:
Dim IsPWDCorrect As Boolean = VerifyHash(sha512Hash, "password here", "password hash from DB")
I also created a function to force user to choose a complex password.
It works on VB.Net Core 6.0
The length of the hash is 128 Byte.
This is an example output:
708ed38ae70f96bc7dcb58515ab328614eaf3b41402de0c50e60ba0f56be5efc6f6daf0b226ec238c3dcaff182e466a1e12df1cadd4e62e6a8c197355b1edc4e

VB.Net and phpMyAdmin: How to connect to phpMyAdmin SQL server without needing a Username or Password?

I'm setting up a Login Form on Visual Basic .Net. I would like to have this database hosted over the internet, so people can connect wherever they are.
The trouble is, security. If I have a username and password in my code, I can easily be hacked, and my program will be cracked.
Is there any way to have a token that I can use instead of a password, that can only be accessed in through the program itself?
This is my code:
Dim connection As New MySqlConnection("datasource=localhost;port-3306;username;whatever;password=whatever;database=whatever")
And this is something like what I'm looking for:
Dim connection As New MySqlConnection("token=aFjiwqMF93JmHSazhH")
If so, how would I do this, and where would I get the database token and link from?
Anyone able to crack your program, will more likely have the knowledge to crack into MySQL too... I know, it's not an answer, I spent many weeks trying to secure my programs against similar, however, I then thought 'Why...?'
That being said, If you really need to keep your source code under wraps and passwords removed, how about loading the connection string from a text file somewhere?
Simple encryption see system.security.cryptography
I have just looked up my old code for encrypting strings simply, you can have a look at this
Imports System.Security.Cryptography
Imports System.Net
Public NotInheritable Class Encryptorr
Public TDS As New TripleDESCryptoServiceProvider
Private Function EncHash(ByVal key As String, ByVal length As Integer) As Byte()
Dim enc_Sha1 As New SHA1CryptoServiceProvider
Dim keyBytes() As Byte =
System.Text.Encoding.Unicode.GetBytes(key)
Dim hash() As Byte = enc_Sha1.ComputeHash(keyBytes)
ReDim Preserve hash(length - 1)
Return hash
End Function
Sub New(ByVal key As String)
TDS.Key = EncHash(key, TDS.KeySize \ 8)
TDS.IV = EncHash("", TDS.BlockSize \ 8)
End Sub
Public Function EncryptData(ByVal plaintext As String) As String
Dim Strbytes() As Byte = System.Text.Encoding.Unicode.GetBytes(plaintext)
Dim memStr As New System.IO.MemoryStream
Dim encStream As New CryptoStream(memStr, TDS.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write)
encStream.Write(Strbytes, 0, Strbytes.Length)
encStream.FlushFinalBlock()
Return Convert.ToBase64String(memStr.ToArray)
End Function
Public Function DecryptData(ByVal encryptedtext As String) As String
Try
Dim enc_Bytes() As Byte = Convert.FromBase64String(encryptedtext)
Dim mem_Str As New System.IO.MemoryStream
Dim decStream As New CryptoStream(mem_Str, TDS.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write)
decStream.Write(enc_Bytes, 0, enc_Bytes.Length)
decStream.FlushFinalBlock()
Return System.Text.Encoding.Unicode.GetString(mem_Str.ToArray)
Catch ex As Exception
Return "Decryption Failed"
End Try
End Function
End Class
Call with
Public Sub TestMe()
Dim encr As Encryptorr = New Encryptorr("AlovelyLong463728KeytoEncryptwith")
Dim encrytedstr As String = encr.EncryptData(textbox1.text)
Textbox2.text = encrytedstr
Dim decry As Encryptorr = New Encryptorr("AlovelyLong463728KeytoEncryptwith")
Dim decryptedtext As String = decry.DecryptData(Textbox2.text)
Textbox3.text = decryptedtext
End Sub
You can then encrypt and decrypt strings read from text files, although back to my original point. If someone can gain access to the program code, they can also work out the decryption too... :(
Still food for thought! Good luck
Update--
Just to add, you could always create the encrytped string, use that as a global variable and the decryt function to pass directly as your connection string. This means isnstead of saving the username and password in a text file, you just use Public Shared Constr as String = fhdasjifhn32437289cj (or whatever the encrypted string is) and the connection would be Dim Con as MySQLConnection = new MySQLConnection(DecryptMyStr(Constr)) with DecryptMyStr being the decrypt function

Decode using available method for encoding in VB

I have this method
Public Shared Function HashPassword(ByVal password As String) As String
Dim algorithm As HashAlgorithm
algorithm = SHA1.Create
Dim data As Byte() = algorithm.ComputeHash(Encoding.UTF8.GetBytes(password))
Dim HashedPassword As String = ""
Dim i As Integer = 0
Do While i < data.Length
HashedPassword &= data(i).ToString("x2").ToLowerInvariant()
i += 1
Loop
Return HashedPassword
End Function
How can I decode a string which has been encoded by this function?
A hash is a one way so you dont decrypt them. Instead, compare the new input value to the stored hash to verify. If you want to encrypt/decrypt data (not the best way to protect passwords), then you need to encrypt, not hash.
But there may be a problem with your method: the result is usually converted to base64 for storing/saving. A hex string might work (never tried) but there is a built in way for this:
Public Shared Function HashPassword(password As String) As String
Dim algorithm As HashAlgorithm
algorithm = SHA1.Create
Dim data As Byte() = algorithm.ComputeHash(Encoding.UTF8.GetBytes(password))
Return Convert.ToBase64String(data)
End Function
So, new user registration would be something like:
hashedPW = HashPassword(thePWText)
To check it later:
thisPW = HashPassword(PWInput)
If thisPW = hashedPW Then
' user knows the PW
Else
' wrong password
End If

Joomla Password Authentication in Visual Basic .NET

I have managed to successfully connect remotely to the MySQL database for my Joomla! 1.5 website using MySqlConnector in Visual Basic .NET 2010.
Now I am trying to authenticate a user's password from values submitted in a simple form to those retrieved from a MySQL query.
I found a useful thread on forums.joomla.org titled "Joomla password MD5 & VB.NET MD5", but the code snippets there produce the incorrect hash.
Here is another useful Joomla Forums thread as to how passwords are encrypted (using MD5 hash and "salt") in the Joomla DB.
Here is a modified version of the code:
Imports System.Text
Imports System.Security.Cryptography
...
Private Function JoomlaUserAuth(ByVal Password As String, ByVal EncryptedPassword As String) As Boolean
'HashedPassword:Salt = value from Joomla DB
Dim Values() As String = Split(EncryptedPassword, ":")
Dim HashedPassword As String = Values(0)
Dim Salt As String = Values(1)
Dim NewHashedPassword As String = GetHash(Password & Salt)
Return NewHashedPassword.Equals(HashedPassword)
End Function
Private Function GetHash(ByVal StringToHash As String) As String
Dim md5 As New MD5CryptoServiceProvider()
Dim encoder As New UTF7Encoding()
Dim encStringBytes As [Byte]()
encStringBytes = encoder.GetBytes(StringToHash)
encStringBytes = md5.ComputeHash(encStringBytes)
Dim strHex As String = String.Empty
For Each B As Byte In encStringBytes
strHex &= String.Format("{0:x2}", B)
Next
Return strHex
End Function
The result is that "NewHashedPassword" and "HashedPassword" are very different using the correct password/DB encrypted password combination. Any ideas?
To get the correct hash for the user password you should input the password twice, something like:
Dim NewHashedPassword As String = GetHash(Password & Password & Salt)

VB.Net Console app to return SHA512 Hash

I'm trying to write a console application in VB.Net (2008) to accept a command line argument input (a password) and output the hash. I modified the code here so that it would accept an argument and I added my own salt/key but the output appears to be incorrect when compared to PHP's output for the same password and salt.
I need something like this so I will have a way to get a SHA512 hash using MS Access VBA. Can you recommend a better solution than what I'm trying or point me to something simpler than the link above? I could possibly post my code here but it's quite long.
Edit1:
I'm using the code from Smerkin Gherkin below now but my PHP hash and my VB.Net hash still does not match. The password and salt I'm using (as a test only) on both are: Password1 abcd1234
My VB.Net code looks like this:
SHA512Hasher.HexHash("Password1", "abcd1234")
My PHP code looks like this:
echo hash_hmac("sha512", "Password1", "abcd1234");
VB.Net returns this:
4E1112E5D2995ECDBF5777BA2B5425B86164044B1564D4A2E0232F5E5BC4A4DA34E9AD8C2E5F664FE795C5ED12753B56563164F239070C45B8278F268A8A0860
PHP returns this:
46d338722b931f2e025ecaa7853da070ad74a4e648c48633388740d647f1edba7f83afe43a104d7f7e0662e130a184743caea39177bc8deda030087d9e425e09
Any ideas what I'm doing wrong?
The simplest option is to use the System.Security.Cryptography.Sha512Managed object. Below is an example that would return SHA512 hash values as base64 strings or as hex strings.
Public Class SHA512Hasher
Private Sub New()
' Prevent instantiation
End Sub
Public Shared Function Base64Hash(ByVal clearText As String) As String
Dim hashedBytes As Byte() = computeHash(clearText)
Return Convert.ToBase64String(hashedBytes)
End Function
Public Shared Function Base64Hash(ByVal clearText As String, ByVal salt As String) As String
Return Base64Hash(salt & clearText)
End Function
Public Shared Function HexHash(ByVal clearText As String) As String
Dim hashedBytes As Byte() = computeHash(clearText)
' Build the hex string by converting each byte.
Dim hexString As New System.Text.StringBuilder()
For i As Int32 = 0 To hashedBytes.Length - 1
hexString.Append(hashedBytes(i).ToString("X2")) ' Use "x2" for lower case
Next
Return hexString.ToString()
End Function
Public Shared Function HexHash(ByVal clearText As String, ByVal salt As String) As String
Return HexHash(salt & clearText)
End Function
Private Shared Function computeHash(ByVal clearText As String) As Byte()
Dim encoder As New Text.UTF8Encoding()
Dim sha512hasher As New System.Security.Cryptography.SHA512Managed()
Return sha512hasher.ComputeHash(encoder.GetBytes(clearText))
End Function
End Class
A simple console application to print some output to the command line is
Module Module1
Sub Main()
Dim clear As String = "Foo"
Dim salt As String = "Salted"
Console.WriteLine(SHA512Hasher.Base64Hash(clear))
Console.WriteLine(SHA512Hasher.Base64Hash(clear, salt))
Console.WriteLine(SHA512Hasher.HexHash(clear))
Console.WriteLine(SHA512Hasher.HexHash(clear, salt))
End Sub
End Module
Edit1 - Updated in response to Edit1 in question
The php function hashes the value with a key which is different to salting the hash (prefixing the clear text with a salt value). The .Net object to use is System.Security.Cryptography.HMACSHA512. An update version of the above code is:
Public Class HMACSHA512Hasher
Private Sub New()
' Prevent instantiation
End Sub
Public Shared Function Base64Hash(ByVal clearText As String) As String
Return Base64Hash(clearText, String.Empty)
End Function
Public Shared Function Base64Hash(ByVal clearText As String, ByVal key As String) As String
Dim hashedBytes As Byte() = computeHash(clearText, key)
Return Convert.ToBase64String(hashedBytes)
End Function
Public Shared Function HexHash(ByVal clearText As String) As String
Return HexHash(clearText, String.Empty)
End Function
Public Shared Function HexHash(ByVal clearText As String, ByVal key As String) As String
Dim hashedBytes As Byte() = computeHash(clearText, key)
' Build the hex string by converting each byte.
Dim hexString As New System.Text.StringBuilder()
For i As Int32 = 0 To hashedBytes.Length - 1
hexString.Append(hashedBytes(i).ToString("x2")) ' Use "x2" for lower case
Next
Return hexString.ToString()
End Function
Private Shared Function computeHash(ByVal clearText As String, ByVal key As String) As Byte()
Dim encoder As New Text.UTF8Encoding()
Dim sha512hasher As New System.Security.Cryptography.HMACSHA512(encoder.GetBytes(key))
Return sha512hasher.ComputeHash(encoder.GetBytes(clearText))
End Function
End Class
I have also changed the hex function to return lower case hash to match the php result.