Tool: MD5 dictionary seed and MD5 Hash Lookup

Tool: MD5 dictionary seed and MD5 Hash Lookup

Update:

I added more functionality to this tool (adding SHA-256 and SHA-512)… see the specifics here: http://sdet.us/updating-md5-tool-to-use-sha-256512-hash/

Concept

Hash Lookup and Seeding:

I put together a tool in Grails that provides a user interface to seed a database with plain text words and their MD5 (not salted) hash. The tool has a secondary component that allows a user to input a MD5 hash into a field and it will search the database for a match. If we have a match, we return the plain text corresponding word.

Below, is how to build the tool in Grails…

Domain Layer

I start in the domain layer.  Really we just need one table that has two fields: word and hash.  So after creating the Grails App, I generate a new Domain.

The domain has two fields like so:

class Dictionary {
 
    String hash
    String word
    static constraints = {
    }
}

Controllers

Next I create a couple controllers… the first controller will be to add words to the dictionary, and it will auto generate MD5 has for each word.  Example: user has a field and inputs the word “food” the word is taken, made into MD5 hash and both the word and has are stored in the dictionary database.

The second controller is going to be used to lookup MD5 hash strings, to see if we have a match in the database, and return the plain text word.

AddToDictionaryController

This controller took from this article on how to generate MD5 hash in Groovy.   The resulting code I added looks like this:

import java.security.MessageDigest
class AddToDictionaryController {
def index() {
}
def submitToDictionary(){
def newWord = params.newWord
def digest = MessageDigest.getInstance("MD5")
def md5hash = new BigInteger(1,digest.digest(newWord.getBytes())).toString(16).padLeft(32,"0")
Dictionary dictionary = new Dictionary()
dictionary.hash = md5hash
dictionary.word = newWord
dictionary.save()
  }
}

The submitToDictionary method takes the text as a parameter being passed in from a web form, and then does the Groovy MD5 processing.  At the end of the method are a few lines instructing Grails to save the word/parameter passed in, as well as the hash generated from that word.

HashLookupController

On the other side of things, we need a controller to handle the logic of taking a request with a MD5 hash and performing a query to the database to see if it exists… if it does, return the plain text word.

My code in this controller looks like this:

class HashLookupController {
 
    def index() {
 
    }
    def lookupHash(){
        def submittedHash = params.submittedHash
        Dictionary dictionary = new Dictionary()
        dictionary.executeQuery("select word from Dictionary where hash = '${submittedHash}'")
    }
}

I’m taking the parameter passed in from the form (The MD5 hash) and I’m passing that hash into a simple SQL query on the dictionary database.  Which will return the word it corresponds to as a result.

Views

The easiest part are the views.  There will be two views for each section (inputing a word, and lookup up a hash.)

Inputing a word:

<g:form controller=”addToDictionary” action=”submitToDictionary”>
<g:textField name=”newWord” id=”newWord” value=”${newWord}” size=”50″/>
<g:submitButton name=”submit”/>
</g:form>

and it’s result page looks like:

&lt;%     nutcracker.Dictionary dictionary = new nutcracker.Dictionary()     def md5Hash = dictionary.executeQuery("select hash from Dictionary where word='${params.newWord}'")[0] %&gt;
word: ${params.newWord}
MD5 Hash: ${md5Hash}

For the MD5 Lookup, the view looks like:

<g:form controller=”hashLookup” action=”lookupHash”>
<g:textField name=”submittedHash” value=”${submittedHash}” id=”submittedHash”/>
<g:submitButton name=”submit”/>
</g:form>

and it’s result page looks like:

&lt;%     nutcracker.Dictionary dictionary = new nutcracker.Dictionary()     def md5HashResult = dictionary.executeQuery("select word from Dictionary where hash='${params.submittedHash}'")[0] %&gt;
The plain text word for your hash is: ${md5HashResult}

Importing a Large Word File

Instead of importing one word at a time.  You can set up a form to import a large dictionary file.  I found this dictionary.txt file online: http://www.math.sjsu.edu/~foster/dictionary.txt

It has a lot of good useful words.  So we can import that whole file and encrypt each word as MD5 with a bit of code… let’s make a new function in the controller:

Update: Adding large word lists from a file: 
 
   def fileToDictionary(){
        request.getFile('fileUpload').inputStream.splitEachLine('\n') { word -&gt;
                println word
                def digest = MessageDigest.getInstance("MD5")
                def md5hash = new BigInteger(1,digest.digest(word[0].getBytes())).toString(16).padLeft(32,"0")
                Dictionary dictionary = new Dictionary()
                dictionary.hash = md5hash
                dictionary.word = word[0]
                dictionary.save()
        }
    }

In the above code, I’m adding the request.getFile(‘fileUpload’).inputStream.splitEachLine(‘\n’) { word ->

Then in the View, we add a form to call this:

<g:uploadForm controller=”addToDictionary” action=”fileToDictionary” method=”post”>
<input type=”file” id=”file” name=”fileUpload”/>
<g:submitButton name=”submit”/>
</g:uploadForm>

Usefulness In Testing

As a tester, I could see this as a good automated test.  Each time a build comes up, run a few hashed passwords in the test database to make sure the MD5 Salting is working.  I can easily imagine a scenario where someone comments out the salting of MD5 Hash for some reason or another and a build goes out where user passwords are MD5 with no salting or other mechanism for encrypting the passwords.

Basically, the code should never just be using MD5 for encryption alone, it should have other mechanisms (salting, etc.) to block a tester from uncovering a known password.

So if in our test environment we have a user login with username: Jim and password: password – we could copy it’s hash from the database, and input it into our test tool (which knows the MD5 hash for the password: password.)  We shouldn’t get a match.

That would prove that bare MD5 isn’t being used.  We could extend upon that test, to also include simple salt (like 1-2 characters.)

Tool: MD5 dictionary seed and MD5 Hash Lookup
User Rating: 0 (0 votes)