• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 466
  • Last Modified:

Delphi code (or component) to check passwords against a dictionary - and a dictionary to use

I am looking for code or a component to check passwords against a dictionary - and it needs to include the dictionary (US).

Something like pam_cracklib over in the UNIX world does.  This is NOT for a Windows password, but for passwords used in our programs. We check for minimum length, types of characters, and repeated passwords but don't have a "dictionary file" to compare the passwords again.  So something like 1Password$ might pass the length and character type checks, but should fail a dictionary check since it uses a common word - a "dictionary word".

A US dictionary file would be a great start, but if someone already has written the code to do the lookups that would be even better.

Thanks
0
dlwynne
Asked:
dlwynne
  • 4
  • 4
  • 3
  • +2
3 Solutions
 
Eddie ShipmanAll-around developerCommented:
Even though this is for you own application, I believe it is against the rules to ask this type of question on E-E because it is considered cracking.
0
 
CodedKCommented:
Hi , the best password list i know of is the Argon :
   http://rs174.rapidshare.com/files/98912262/theargonlistver2_wordlist.zip

Plain text is almost 2 gigs !

Hope this helps.
0
 
ThievingSixCommented:
Alright I think I know what your getting at.

You can find some good text files here: http://wordlist.sourceforge.net/

When you need to search for a word in the long list quickly you would load the text file(in sections even) and do something like this: http://www.swissdelphicenter.ch/torry/printcode.php?id=1916
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
CodedKCommented:
More often password lists are always sorted !

(Binary search needs the list to be sorted before it runs) ....So its best to remove Quicksort function from the code above because its going to iterate through the whole list every time you run the code...
Binary search is of course the best way unless you're feeling lucky (brute force), so just remove the
QuickSort call.
0
 
ThievingSixCommented:
Well if you read the entire page you would have read that you need to sort the list first, if it's already sorted then of course you wouldn't need to. It's there for the reference.

Also, CodedK, this isn't about a password list(as far as I can tell). He's trying to make sure people that enter passwords don't use common words such as you would find in the dictionary.
0
 
CodedKCommented:
Password list or dictionary file is exactly the same for me for this kind of task :)
Unless he needs it for vacations to US then its useless :D hehe
Maybe my comment was pointless, i was just posting my thoughts.
Neeeed cofeee
0
 
aikimarkCommented:
Rather than doing a string-comparing search against a list/array of strings, you would get much better results by comparing a hash of the password against hashes of the dictionary entries.  Integer comparisons are sooooo much faster than string comparisons.

In fact, you might be able to represent the hash positions as a bit-array or byte-array and greatly reduce the memory footprint as well as make the matching nearly instantaneous.

================
dictionary sources links
http://wordlist.sourceforge.net/
ftp://ftp.ox.ac.uk/pub/wordlists/american/ 

0
 
dlwynneAuthor Commented:
Thanks for the list links, ThievingSix and CodedK.  The massive Argon list is probably way too big for what I want to do, but the smaller Argon list or the ones I downloaded from the wordlist lnk probably will do - in some form or other.

I want something quick, like when assigning or changing a password under LINUX and it does not have to block the use of EVERY possible dictionary work - just the most common ones.

ThievingSix, I have used binary search many times and understand its use - and it can be very fast on a sorted list of items.  The problem I see is that I am not sure I can use it in this case.

Example:  someone wants to use 1mypassword$ for their password. I can code it to remove the non characters and then binary search the dictionary - but that means I search on mypassword which it will not find.  What I really should do is check to see if each of the dictionary words exists in the password

x:=0;
while(x<number_of_words_in_dictionary) do
begin
  if(pos(dictionary[x],new_password) > 0)then
  begin
     {bad password}
     x:=number_of_words_in_dictionary+1;
  end
  else
  begin
    inc(x);
  end;
end;

This would catch either "my" or "password" and not let them use it.

Any ideas how to speed that search up rather than the code like I posted?

0
 
dlwynneAuthor Commented:
aikimark,

Thanks for the additional word list link.

Got some example code of your hash idea?   As I posted just above, I can't (or don't want to) do an exact match I would like to check the new password to see if it contains any of the dictionary words.

0
 
aikimarkCommented:
you can't do that with hashing.  it's an all-or-nothing match.
0
 
dlwynneAuthor Commented:
I am thinking I should sort the words by length, shortest to longest.  Then drop any shorter than say 3 or 4 characters and any longer than say 10. The resulting file would be my "dictionary" to check against. These would all be mapped to lower case and would have any words with special characters removed from the list.

I would load these into memory in this sorted order.

In my code would be something like this:

new_password_temp:=strip_non_alpha(new_password);
new_password_temp:=lowercase(new_password_temp);
backwards_password:=reverse_the_string(new_password_temp);
x:=0;
password_ok:=true;
while(x< words_in_dictionary) do
begin
  if((pos(dictionary[x], new_password_temp) or (pos(dictionary[x].backwards_password))then
  begin
     password_ok:=false;
     x:=words_in_dictionary+1;
  end
  else
  begin
    inc(x);
    if(length(dictionary[x]) > new_password_temp)then
    begin
         x:=words_in_dictionary+1;
    end;
  end;
end;

0
 
aikimarkCommented:
I think you're missing a comma
dictionary[x].backwards_password
 
should be
dictionary[x], backwards_password

Open in new window

0
 
dlwynneAuthor Commented:
Thanks, I didn't try the code - just typed it in :-) .

We are toying with the idea of doing it differently.  We could take the first 3 (say) characters and compare to the 3 character dictionary words, perhaps hashed by starting letter, then move on the first 4, the 5, etc,. If no match found, then we would do the 2nd-4th, then 2nd-5th, 2nd-6th, then 3rd-6th, 3rd-7th, etc. Rather than searching through all dictionary words to see if they are in the password, break the password string up and search for exact macthed in the dictionary list.

So a new password of "mypassword" might be checked as "myp", then "mypa", then "mypass", etc, then "ypa", "ypas", "ypass", etc then "pas", "pass" (finds a match and is rejected here or when it hits "password").

0
 
aikimarkCommented:
It would result in simpler code if you used some wildcard pattern matching, such as TRegEx class or, probably just used ANSIPos() to look for any non-zero value of the dictionary word in the typed password string.

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 4
  • 4
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now