A simple password guesser

Last night when I couldn’t fall asleep all kinds of weird ideas kept flowing through my head. One of them was to write an AppleScript that could crack a password. So… having nothing better to do, I just wrote one. I’m not an expert scripter so there’s probably a lot that could be done cleaner and more efficient. If you want to chime in, you’re most welcome.

I considered compiling a list of wrong guesses to avoid repeating the same guess more than once, but it seemed to slow the process down considerably so I dropped it.

Judging from Activity Monitor, the script uses only one core on my dual core iMac. Is there any way to make it use both?

The variable appRate calculates the approximate rate (guesses per second) that can be expected. The equation I use to calculate this is one I got from Excel after having plotted several datapoints in a scatter chart and add a trendline. So the estimated number of guesses per second is based on my computer’s performance. However, if the script guesses your password, it will output the actual number of guesses it made.

set myPassword to text returned of (display dialog "Enter a password to guess" default answer "")
set passLength to count characters of myPassword
considering case
	set lowerCase to "abcdefghijklmnopqrstuvwxyz"
	set upperCase to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	set theNumbers to "1234567890"
	set theSymbols to "$§!\"#€%&/()=?`¡"§£âˆžâ„¢¶[]≠±'°âˆ‘é® ¥Ã¼|Å“Ï€˜~ªÃŸâˆ‚Æ’©«¹âˆ†¬Ã¤Ã¶@Ω.ç√∫ñµ<>≤≥,.-;:_žÃ·”"
	set lowerCaseUsed to false
	set upperCaseUsed to false
	set theNumbersUsed to false
	set theSymbolsUsed to false
	repeat with i from 1 to passLength
		if character i of myPassword is in lowerCase then
			set lowerCaseUsed to true
		else if character i of myPassword is in upperCase then
			set upperCaseUsed to true
		else if character i of myPassword is in theNumbers then
			set theNumbersUsed to true
		else if character i of myPassword is in theSymbols then
			set theSymbolsUsed to true
		end if
	end repeat
	set usedCharacters to ""
	if lowerCaseUsed then set usedCharacters to usedCharacters & lowerCase
	if upperCaseUsed then set usedCharacters to usedCharacters & upperCase
	if theNumbersUsed then set usedCharacters to usedCharacters & theNumbers
	if theSymbolsUsed then set usedCharacters to usedCharacters & theSymbols
	try
		set noPossibilities to ((count usedCharacters) ^ passLength) as integer
	on error
		set noPossibilities to ((count usedCharacters) ^ passLength)
	end try
	try
		set appRate to 61448 * (noPossibilities ^ -0.054) as integer
	on error
		set appRate to 61448 * (noPossibilities ^ -0.054)
	end try
	display dialog "There are " & noPossibilities & " possibilities." & return & "At app. " & appRate & " guesses per second this will take" & return & convertTime((noPossibilities / appRate)) & " to guess." buttons {"Cancel", "Go ahead!"} default button "Cancel"
	set correct to false
	set wrongGuesses to 0
	set timeStart to (current date)
	repeat until correct
		set theGuess to ""
		set theGuess to some character of usedCharacters
		repeat (passLength - 1) times
			set theGuess to theGuess & some character of usedCharacters
		end repeat
		if theGuess is not myPassword then
			set wrongGuesses to wrongGuesses + 1
		else
			set correct to true
		end if
	end repeat
end considering
set timeStop to (current date)
set timeTaken to (timeStop - timeStart)
if timeTaken < 1 then set timeTaken to 1
return "Your password is " & theGuess & ". It took " & timeTaken & " seconds and " & wrongGuesses & " guesses @ " & ((wrongGuesses / timeTaken) as integer) & " guesses per second." & return & return & "There were " & noPossibilities & " possibilities."

on convertTime(input)
	if input is less than minutes then
		set output to ((input as integer) as string) & " seconds"
	else if input is less than hours then
		set myMins to input div minutes
		set mySecs to input mod minutes
		set output to (myMins as string) & " minutes and " & (mySecs as integer) & " seconds"
	else if input is less than days then
		set myHours to input div hours
		set myMins to input mod hours div minutes
		set output to (myHours as string) & " hours and " & myMins & " minutes"
	else if input is less than ((days * 365) / 12) then
		set myDays to input div days
		set myHours to input mod days div hours
		set output to (myDays as string) & " days and " & myHours & " hours"
	else if input is less than (days * 365) then
		set myMonths to input div ((days * 365) / 12)
		set myDays to input mod ((days * 365) / 12) div days
		set output to (myMonths as string) & " months and " & myDays & " days"
	else if input ≥ (days * 365) then
		set myYears to input div (days * 365)
		set myMonths to input mod (days * 365) div ((days * 365) / 12)
		set output to (myYears as string) & " years and " & myMonths & " months"
	end if
	return output
end convertTime

No. AppleScript is not multi-threaded unless you run some part that can run in parallel as a shell script.