To give you an idea:
Public Class PasswordFinder
Private Const AllowedChars As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
Private Const CharsetSizeMinus1 As Integer = 61
Private TheCharset() As Byte
Private HashToSearch() As Byte
Private TheHasher As New System.Security.Cryptography.MD5CryptoServiceProvider
Public Sub New()
If CharsetSizeMinus1 + 1 <> AllowedChars.Length Then Throw New Exception("Make sure that charsetsize is correct!")
' Fill our charset array
ReDim TheCharset(AllowedChars.Length - 1)
For i As Integer = 0 To AllowedChars.Length - 1
TheCharset(i) = Asc(AllowedChars.Substring(i, 1))
Next
End Sub
Public Sub test()
Dim pw As String = "9999" ' worst case in current setup
Dim encoding As New System.Text.ASCIIEncoding()
HashToSearch = TheHasher.ComputeHash(encoding.GetBytes(pw))
Dim t As Date = Now
FindPassword(4)
MsgBox("Found in " & (Now - t).Duration.ToString)
End Sub
Private Function FindPassword(ByVal MaxLength As Integer) As Boolean
If MaxLength < 1 Or MaxLength > 8 Then Throw New Exception("bump")
Dim count As Integer = MaxLength
Dim offset As Integer = 8 - MaxLength
Dim b(7) As Byte
Dim h() As Byte
Dim i As Integer
Dim i7 As Integer, i6 As Integer, i5 As Integer, i4 As Integer
Dim i3 As Integer, i2 As Integer, i1 As Integer, i0 As Integer
For i3 = 0 To CharsetSizeMinus1
b(3) = TheCharset(i3)
For i4 = 0 To CharsetSizeMinus1
b(4) = TheCharset(i4)
For i5 = 0 To CharsetSizeMinus1
b(5) = TheCharset(i5)
For i6 = 0 To CharsetSizeMinus1
b(6) = TheCharset(i6)
For i7 = 0 To CharsetSizeMinus1
b(7) = TheCharset(i7)
h = TheHasher.ComputeHash(b, offset, count)
' compare the two hashes:
For i = 0 To 15
If h(i) <> HashToSearch(i) Then GoTo notfound
Next
' if we are here, we found the hash
' we need to save the found pw and do other stuff,
' but for now we simply ...
Return True
notfound:
Next i7
If MaxLength = 1 Then GoTo final
Next i6
If MaxLength = 2 Then GoTo final
Next i5
If MaxLength = 3 Then GoTo final
Next i4
If MaxLength = 4 Then GoTo final
Next i3
If MaxLength = 3 Then GoTo final
final:
Return False ' should never be reached of course
End Function
End Class
In debug mode and on my little notebook, it takes 2 minutes 35 seconds to find the worst case 4 char password.
I have ommited the i2 to i0 loops - trivial to add.
Options for improvement:
- create single functions for each pw-len. This removes the "if maxlength" checks.
- find a faster hash-compare function
- if multicore, use single functions that check half of the charset, or a quarter or whatever the number of cores is.
- play with private, public, shared, const etc declarations
- ???
Basically improving speed can be done by bloating the code with copy&paste work. As a rule of thumb: You pay for improvement in performance with code size.
btw: your original code works with "string". The hasing function work on byte level, so creating a string that later has to be converted to byte does not make sense.
EDIT:
With all optimizations, I hardly get any improvement.
If I comment the "computhash" part and work with an empty h() (which of course never matches) the app runs around .23 seconds. So obviously the password CREATION is not the problem, but the CHECKING. I guess I already said that in the beginning.
To improve: Switch to unmanaged C/C++