Decrypting MD5 in VB.NET FORM DATABASE - vb.net

I'm having trouble in decrypting may password that came from database and send to email recovery. here's the code to encrypt my password.
Dim des As New TripleDESCryptoServiceProvider
Dim md5 As New MD5CryptoServiceProvider
'we need to make hash function
Function md5hash(ByVal password)
Return md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(password))
End Function
'now we can create function by using this has
Function encrypt(ByVal strings, ByVal key)
des.Key = md5hash(key)
des.Mode = CipherMode.ECB
Dim buffer = ASCIIEncoding.ASCII.GetBytes(strings)
Return Convert.ToBase64String(des.CreateEncryptor().TransformFinalBlock(buffer, 0, buffer.length))
End Function
and here it's how to encrypt
Dim cs As New Functions
Dim strText As String = newpassword.Text
Dim bytHashedData As Byte()
Dim encoder As New UTF8Encoding()
Dim md5Hasher As New MD5CryptoServiceProvider
Dim md5 As New md5
Dim data1 As String
data1 = md5.encrypt(newpassword.Text, "This is key")
Dim data2 As String
data2 = md5.encrypt(oldpassword.Text, "This is key")
If cs.checklogin(oldpassword.Text, newpassword.Text) = False Then
If cs.checkusername(UserName.Text) = True Then
If cs.checkpass(data2) = True Then
If cs.changepass(data1, UserName.Text) = False Then
MessageBox.Show("Password changed successfully.")
bytHashedData = md5Hasher.ComputeHash(encoder.GetBytes(strText & newpassword.Text))
UserName.Text = ""
oldpassword.Text = ""
newpassword.Text = ""
Else
MessageBox.Show("Something Went wrong!")
End If
Else
MessageBox.Show("Old password is incorect!")
End If
Else
MessageBox.Show("Username not found!")
End If
Else
MessageBox.Show("We strictly comply completing all required fields.")
End If
End Sub
what should I do to get the password from the database to to decrypt my password.

MD5 is hashing, not encryption. A large part of the reason hashing is used for this is because it's not reversible; that is, once hashed, your password is never supposed to be recovered. Only by accepting a password from a user and comparing its hash to the one you've saved should you be able to tell that it's accurate.
That said, MD5 is a very poor algorithm to use on its own, as will be noted in most comments.
Email password 'recovery' is about resetting the password; one approach is to generate a separate time-limited hash to construct a URL to send to the user that presents a password reset form. If the hash matches, use that form to accept and then hash (look into switching to bcrypt if that's an option you have) and save the new password the user provides.

Related

Encrypting and Decrypting a Serialized Object

Okay, so I am attempting to create a system whereby I serialize a dictionary, then encrypt it and then can decrypt it and then restore the dictionary.
It also includes some selection statements based on a setting whereby the user sets whether to always, never or prompt for encryption.
I have been attempting to follow along with the CryptoStream Class documentation, but for some reason this isn't working. I think the encryption might be working, but the file is a lot smaller than the none encrypted .ser equivalent so I don't know. The decryption generates an "Attempting to deserialize an empty stream." error, which is pretty self explanatory, but I can't work out how to fix it.
The backup and restore works fine without encryption.
Here are the relevant subroutines (and the GIT link if it's easier) and any help would be hugely appreciated! This is for an A Level computing project, so I'm not too fussed about the actual strength of the encryption (really don't want to start faffing around with hashing AND salting), just that it works.
Encrypt Backup:
Private Sub encryptBackup()
Dim key As Byte()
Dim IV As Byte() = New Byte() {}
Using MD5 As New MD5CryptoServiceProvider
Dim tmp = System.Text.Encoding.UTF8.GetBytes(InputBox("Please insert password:", "Password Input") & "This is most definitely not an obtuse amount of salt")
key = MD5.ComputeHash(tmp)
IV = MD5.ComputeHash(key)
End Using
Using cryptoRijndael = Rijndael.Create()
Dim cryptoCryptor As ICryptoTransform = cryptoRijndael.CreateEncryptor(key, IV)
Using fStream As New FileStream(fldBackupJobs & "\Backup Files\" & Strings.Replace(Strings.Replace(Now, ":", "_"), "/", ".") & ".bin", FileMode.OpenOrCreate), cStream As New CryptoStream(fStream, cryptoCryptor, CryptoStreamMode.Write)
Dim Formatter As New BinaryFormatter
Formatter.Serialize(cStream, photoJobs)
MsgBox("Written to file")
End Using
End Using
End Sub
Decrypt Backup:
Private Sub decryptBackup(pathsStr As String)
photoJobs = Nothing
Dim key As Byte()
Dim IV As Byte() = New Byte() {}
Using MD5 As New MD5CryptoServiceProvider
Dim tmp = System.Text.Encoding.UTF8.GetBytes(InputBox("Please insert password:", "Password Input") & "This is most definitely not an obtuse amount of salt")
key = MD5.ComputeHash(tmp)
IV = MD5.ComputeHash(key)
End Using
Using cryptoRijndael = Rijndael.Create()
Dim cryptoCryptor As ICryptoTransform = cryptoRijndael.CreateEncryptor(key, IV)
pathstr = OpenFileDialog.FileName
Using fStream As New FileStream(pathstr, FileMode.Open), cStream As New CryptoStream(fStream, cryptoCryptor, CryptoStreamMode.Read)
Dim Formatter As New BinaryFormatter
photoJobs = CType(Formatter.Deserialize(cStream), Dictionary(Of String, PhotoJob))
MsgBox("Backup Restored")
End Using
End Using
End Sub
And the GIT Link: https://github.com/hughesjs/Photo-Gift-Manager
Thanks In Advance!!
The first part of the code gives me pause because (beyond GoTo) it looks like the crypto method is dependent upon the file extension. Since the user could change this via Explorer, it is very brittle. And dont let the user choose: if it is needs to be encrypted, do it; if not, don't. Certainly, the encryption method ought not be up to them (we get the big bucks to make those decisions for them).
Encrypting using a a BindingList(of Animal) which I happen to have handy:
Dim key As Byte()
Dim iv As Byte() = New Byte() {}
' see notes below
Using MD5 As New MD5CryptoServiceProvider
' UTF8 not unicode; convert password to Byte()
Dim tmp = Encoding.UTF8.GetBytes(password & "$*^!#" & password)
' hash the PW to get the crypto Key
key = MD5.ComputeHash(tmp)
' hash the Key to get the IV
iv = MD5.ComputeHash(key)
End Using
Using rijAlg = Rijndael.Create()
' Create cryptor using the Key and IV
Dim cryptor As ICryptoTransform = rijAlg.CreateEncryptor(key, IV)
' Open a filestream for the output file, wrap it with
' a CryptoStream created with the cryptor in WRITE (output) mode
Using fs As New FileStream("C:\Temp\crypto.bin", FileMode.OpenOrCreate),
cs As New CryptoStream(fs, cryptor, CryptoStreamMode.Write)
' serialize collection to CryptoStream (to disk)
Dim bf As New BinaryFormatter
bf.Serialize(cs, mcol)
End Using
End Using
To decrypt, use the same Key and IV:
mcol = Nothing
' the comments above pertain, just in reverse
Using rijAlg = Rijndael.Create()
Dim cryptor As ICryptoTransform = rijAlg.CreateDecryptor(key, iv)
Using fs As New FileStream("C:\Temp\crypto.bin", FileMode.Open),
cs As New CryptoStream(fs, cryptor, CryptoStreamMode.Read)
Dim bf As New BinaryFormatter
' Convert object to type
mcol = CType(bf.Deserialize(cs), BindingList(Of Animal))
End Using
End Using
' test:
For Each a As Animal In mcol
Console.WriteLine(a.Name)
Next
All my animals survived the trip:
Rover
Gizmo
Ziggy
The main thing appears to be that you have too many streams in use. In your decrypter you are trying to deserialize from a memstream which has nothing to do with the cryptostream that reads the file. In fact it was just created the line before. A cryptostream basically just wraps whatever "real" stream you are using.
Also, this line shows you are not using Option Strict:
photoJobs = formatter.Deserialize(memStreamSerial)
Deserialize returns an Object and photoJobs is some sort of collection IIRC from past posts. Note that my code uses CType to convert to BindingList(Of Animal).
Use Option Strict for anything more complex than 'Hello, World`. Always.
Crypto Notes / Cautions
Deriving (hashing) the IV from the password is a bad idea: these should be independent pieces of data. The IV should be unique for each piece of data (which will not be the case when a PW is reused) and unique. I added some arbitrary text to the PW so that the MD5 hash is not directly derived from teh PW, but it is still suboptimal.
Secondly, MD5 is outdated.
To create a random IV
Private Const MinSize = 7
Public Shared Function GetRandomBytes(size As Integer) As Byte()
' dont allow less than a sensible min
Dim data(If(size < MinSize, MinSize, size)) As Byte
Using rng As New RNGCryptoServiceProvider
' fill the array
rng.GetNonZeroBytes(data)
End Using
Return data
End Function
Put this in a crypto tools lib because you will use it for IV's as well as Salt for hashes. Example:
myIV = CryptoUtils.GetRandomBytes(15)
If the IV is unique each time, the trick becomes how to save it so the same values can be used in decryption. The IV need not be secret, so it can be saved to the FileStream before you pass it to the CryptoStream constructor. The Decrypt method does the reverse.
These too can be made into methods so the same process is used each time.
Finally, your questions will get a better reception if they were more concise. The error clearly indicates a crypto problem so those first 2 blocks are more or less noise.

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

Hash with MD5 in 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

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)

Invalid character in a Base-64 string when attempting decryption

I have a encryption/decryption method that works just fine with one exception. When I attempt to read in encrypted text from a text file and then decrypt it I get the following error.
Invalid character in a Base-64 string
The strange thing is if I just read the encrypted text into a textbox and then copy and pate it into another text box that decrypts used the same decryption method it works just fine. No errors and the decryption proceeds. I am listing the decryption method and method used to read in the text file below.
Decryption Method
Public Shared Function DecryptUserString(ByRef cipheredText As String, ByRef password As String) As String
Dim RijndaelManagedObj As New RijndaelManaged
Dim RijndaelEncObj As ICryptoTransform, MD5Obj As New MD5CryptoServiceProvider
Dim DecryptedBytes As Byte(), EncryptedData As Byte()
Dim PasswordBytes As Byte() = New ASCIIEncoding().GetBytes(password)
Dim UTF8Encoding As System.Text.Encoding = System.Text.Encoding.UTF8
'A modified Base64 is sent with ~ and - so it can be sent as a form post
EncryptedData = Convert.FromBase64String(Replace(Replace(cipheredText, "~", "+"), "-", "="))
RijndaelManagedObj.BlockSize = 128
RijndaelManagedObj.KeySize = 128
RijndaelManagedObj.Mode = CipherMode.ECB
RijndaelManagedObj.Padding = PaddingMode.None
RijndaelManagedObj.Key = MD5Obj.ComputeHash(PasswordBytes)
RijndaelEncObj = RijndaelManagedObj.CreateDecryptor()
DecryptedBytes = RijndaelEncObj.TransformFinalBlock(EncryptedData, 0, EncryptedData.Length)
If DecryptedBytes.Length > 0 Then
DecryptUserString = UTF8Encoding.GetString(DecryptedBytes, 0, DecryptedBytes.Length)
If DecryptedBytes.Length = 0 Then DecryptUserString = New ASCIIEncoding().GetString(DecryptedBytes)
Else
DecryptUserString = ""
End If
End Function
Method to read text from file
Private Function ReadText(ByVal TextFilePath As String) As String
Using ReadStream As FileStream = File.OpenRead(TextFilePath)
Dim FileTextBuilder As New StringBuilder()
Dim DataTransit As Byte() = New Byte(ReadStream.Length) {}
Dim DataEncoding As New UTF8Encoding(True)
While ReadStream.Read(DataTransit, 0, DataTransit.Length) > 0
FileTextBuilder.Append(DataEncoding.GetString(DataTransit))
End While
Return FileTextBuilder.ToString()
End Using
End Function
Can't you use File.ReadAllText() method to read the whole file and then decrypt the same way you do with textboxes?
I know, if file is huge that's not a good idea, but you can give it a try to see if file is well saved or if you're reading it bad.