Site unique password system

As a part of a system-wide AI script (Why and I doing this in applescript? Nevermind…) I have a password system. It takes:

¢ the ‘name’ of a website (e.g. macscripter)
¢ a user set password string (e.g. mysuperpassword) which can be used on all sites
¢ a password length (default 10)

and scrambles it all together beautifully, adding in at least one £ sign in the front (password breakers tend to ignore foreign currency symbols) and tries to reach the number of characters.

The result is using one memorable password to generate a secure, different password for each website which you don’t need to remember. Just use the script to get the password back because it’ll give the same answer each time.

Finally it copies your password to the clipboard to be pasted into a password box and after 5 seconds clears the clipboard to stop someone pasting it into a text document or something and discovering it.


set input to the text returned of (display dialog "Site name:" default answer "" buttons {"OK"} default button 1)
set secCode to the text returned of (display dialog "Security code:" default answer "" buttons {"OK"} default button 1 with hidden answer)
set totlength to the text returned of (display dialog "Password length:" default answer "10" buttons {"OK"} default button 1) as number


set timeunit to (round ((hours of (current date)) / 6) rounding down) + 1

set sLetterSet to {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}

set cLetterSet to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}

set numberSet to {"2", "6", "8", "0", "7", "4", "5", "7", "0", "1", "0", "9", "5", "7", "6", "2", "9", "8", "4", "5", "1", "3", "2", "3", "8", "4"}

set specialSet to {"!", "$", "%", "£", "^", "&", "*", ")", "-", "+", "=", "[", "{", ";", "'", ":", "|", ",", ".", "/", "?", "<", "±", "§", "`", "~"}

set totlength to totlength - 1

set finNum to 0
repeat with i from 1 to the number of characters in input
	set finNum to finNum + (ASCII number (character i of input))
end repeat

repeat
	if finNum > 40 then
		set finNum to finNum - 40
	else
		exit repeat
	end if
end repeat

set pusher to sLetterSet & cLetterSet & numberSet & specialSet as text

set worker to ""
repeat with i from 1 to the number of characters in input
	set pos to ((offset of (character i of input) in pusher) + finNum * i * i)
	repeat
		if pos > 104 then
			set pos to pos - 104
		else
			exit repeat
		end if
	end repeat
	set worker to worker & character pos of pusher
end repeat
set input to worker

set finNum to 0
repeat with i from 1 to the number of characters in secCode
	set finNum to finNum + (ASCII number (character i of secCode))
end repeat

repeat
	if finNum > 40 then
		set finNum to finNum - 40
	else
		exit repeat
	end if
end repeat

set worker to ""
repeat with i from 1 to the number of characters in secCode
	set pos to ((offset of (character i of secCode) in pusher) + finNum * i * i)
	repeat
		if pos > 104 then
			set pos to pos - 104
		else
			exit repeat
		end if
	end repeat
	set worker to worker & character pos of pusher
end repeat
set secCode to worker

set worker to ""
repeat with i from 1 to the number of characters in input
	set pos to ((offset of (character i of input) in pusher) + finNum * i * i)
	repeat
		if pos > 104 then
			set pos to pos - 104
		else
			exit repeat
		end if
	end repeat
	set worker to worker & character pos of pusher
end repeat
set input to worker

set finpw to ""
if the number of characters in input > the number of characters in secCode then
	repeat with i from 1 to the number of characters in secCode
		set numToPush to (offset of (character i of secCode) in pusher) + (offset of (character i of input) in pusher)
		repeat
			if numToPush > 104 then
				set numToPush to numToPush - 104
			else
				exit repeat
			end if
		end repeat
		set finpw to finpw & character numToPush of pusher
	end repeat
else
	repeat with i from 1 to the number of characters in input
		set numToPush to (offset of (character i of secCode) in pusher) + (offset of (character i of input) in pusher)
		repeat
			if numToPush > 104 then
				set numToPush to numToPush - 104
			else
				exit repeat
			end if
		end repeat
		set finpw to finpw & character numToPush of pusher
	end repeat
end if

if the number of characters in finpw > totlength then
	set worker to finpw
	set finpw to ""
	repeat with i from 1 to totlength
		set finpw to finpw & character i of worker
	end repeat
else if the number of characters in finpw < totlength then
	set finpw to finpw & input & secCode
	if the number of characters in finpw < totlength then
		set finpw to finpw & input & secCode & (specialSet) as text
	end if
	set worker to finpw
	set finpw to ""
	repeat with i from 1 to totlength
		set finpw to finpw & character i of worker
	end repeat
end if
set finpw to "£" & finpw
set the clipboard to finpw
beep 2
delay 5
if (the clipboard) is finpw then
	set the clipboard to ""
end if
beep 2

Also… I’ve posted the code here. So if your (or my) laptop dies, you can get the passwords back!

Model: MacBook
AppleScript: 2.3
Browser: Google Chrome
Operating System: Mac OS X (10.6)

Oh, and here’s my personal version with a little more extra-script supporty stuff (external variables and a separate speech handling program.) This is also one of my backups.


set knownPassFile to (load script alias "Reaver:Users:fisto:Code Box:Applescript:Automation:Ultimate AI:Variable files:Password Variables.scpt")
set knownPassDetails to knownPassDetails of knownPassFile
set inputall to (display dialog "Site name:" default answer "" buttons {"OK", "AlphaNumeric"} default button 1)
set input to the text returned of inputall
if the button returned of inputall is "OK" then
	set finpw to "£"
	set specialSet to {"a", "4", "f", "3", "6", "g", "b", ")", "-", "+", "=", "[", "{", ";", "'", ":", "|", ",", ".", "/", "?", "<", "±", "§", "`", "~"}
else
	set finpw to "A"
	set specialSet to {"h", "g", "3", "0", "d", "j", "t", "d", "i", "c", "l", "k", "n", "i", "4", "9", "0", "s", "v", "i", "s", "d", "v", "9", "5", "4"}
end if
set totlength to 10
set new to 1
try
	set sites to {}
	repeat with i from 1 to the number of items in knownPassDetails
		set sites to sites & {siteName of item i of knownPassDetails}
	end repeat
	if input is in sites then
		repeat with i from 1 to (the number of items in knownPassDetails)
			if input is (item i of sites) then
				set totlength to passLength of item i of knownPassDetails
				exit repeat
				if passType of item i of knownPassDetails is "OK" then
					set finpw to "£"
					set specialSet to {"a", "4", "f", "3", "6", "g", "b", ")", "-", "+", "=", "[", "{", ";", "'", ":", "|", ",", ".", "/", "?", "<", "±", "§", "`", "~"}
				else
					set finpw to "A"
					set specialSet to {"h", "g", "3", "0", "d", "j", "t", "d", "i", "c", "l", "k", "n", "i", "4", "9", "0", "s", "v", "i", "s", "d", "v", "9", "5", "4"}
				end if
			end if
		end repeat
		set new to 0
	end if
on error e
	speakTxt("No password files.")
end try
set secCode to the text returned of (display dialog input & return & "Security code:" default answer "" buttons {"OK"} default button 1 with hidden answer)
if new is 1 then
	set secCode2 to the text returned of (display dialog "re-enter Security code:" default answer "" buttons {"OK"} default button 1 with hidden answer)
	if secCode is not secCode2 then
		speakTxt("Security codes do not match.")
		return "Bad security"
	end if
end if
set totlength to the text returned of (display dialog "Password length:" default answer totlength buttons {"OK"} default button 1) as number
if new is 1 then
	set knownPassDetails of knownPassFile to knownPassDetails of knownPassFile & {{siteName:input, passLength:totlength, passType:(the button returned of inputall)}}
	store script knownPassFile in alias "Reaver:Users:fisto:Code Box:Applescript:Automation:Ultimate AI:Variable files:Password Variables.scpt" with replacing
end if

set timeunit to (round ((hours of (current date)) / 6) rounding down) + 1

set sLetterSet to {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}

set cLetterSet to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}

set numberSet to {"2", "6", "8", "0", "7", "4", "5", "7", "0", "1", "0", "9", "5", "7", "6", "2", "9", "8", "4", "5", "1", "3", "2", "3", "8", "4"}

set totlength to totlength - 1

set finNum to 0
repeat with i from 1 to the number of characters in input
	set finNum to finNum + (ASCII number (character i of input))
end repeat

repeat
	if finNum > 40 then
		set finNum to finNum - 40
	else
		exit repeat
	end if
end repeat

set pusher to sLetterSet & cLetterSet & numberSet & specialSet as text

set worker to ""
repeat with i from 1 to the number of characters in input
	set pos to ((offset of (character i of input) in pusher) + finNum * i * i)
	repeat
		if pos > 104 then
			set pos to pos - 104
		else
			exit repeat
		end if
	end repeat
	set worker to worker & character pos of pusher
end repeat
set input to worker

set finNum to 0
repeat with i from 1 to the number of characters in secCode
	set finNum to finNum + (ASCII number (character i of secCode))
end repeat

repeat
	if finNum > 40 then
		set finNum to finNum - 40
	else
		exit repeat
	end if
end repeat

set worker to ""
repeat with i from 1 to the number of characters in secCode
	set pos to ((offset of (character i of secCode) in pusher) + finNum * i * i)
	repeat
		if pos > 104 then
			set pos to pos - 104
		else
			exit repeat
		end if
	end repeat
	set worker to worker & character pos of pusher
end repeat
set secCode to worker

set worker to ""
repeat with i from 1 to the number of characters in input
	set pos to ((offset of (character i of input) in pusher) + finNum * i * i)
	repeat
		if pos > 104 then
			set pos to pos - 104
		else
			exit repeat
		end if
	end repeat
	set worker to worker & character pos of pusher
end repeat
set input to worker

set finpw to ""
if the number of characters in input > the number of characters in secCode then
	repeat with i from 1 to the number of characters in secCode
		set numToPush to (offset of (character i of secCode) in pusher) + (offset of (character i of input) in pusher)
		repeat
			if numToPush > 104 then
				set numToPush to numToPush - 104
			else
				exit repeat
			end if
		end repeat
		set finpw to finpw & character numToPush of pusher
	end repeat
else
	repeat with i from 1 to the number of characters in input
		set numToPush to (offset of (character i of secCode) in pusher) + (offset of (character i of input) in pusher)
		repeat
			if numToPush > 104 then
				set numToPush to numToPush - 104
			else
				exit repeat
			end if
		end repeat
		set finpw to finpw & character numToPush of pusher
	end repeat
end if

if the number of characters in finpw > totlength then
	set worker to finpw
	set finpw to ""
	repeat with i from 1 to totlength
		set finpw to finpw & character i of worker
	end repeat
else if the number of characters in finpw < totlength then
	set finpw to finpw & input & secCode
	if the number of characters in finpw < totlength then
		set finpw to finpw & input & secCode & (specialSet) as text
	end if
	set worker to finpw
	set finpw to ""
	repeat with i from 1 to totlength
		set finpw to finpw & character i of worker
	end repeat
end if
set finpw to finpw & finpw
set the clipboard to finpw
speakTxt("Password set in clipboard.")
delay 10
if (the clipboard) is finpw then
	set the clipboard to ""
end if

on speakTxt(inputValues)
	set queue to load script alias "Reaver:Users:fisto:Code Box:Applescript:Automation:Ultimate AI:Queues.scpt"
	set SpeechQueue of queue to SpeechQueue of queue & inputValues
	store script queue in "Reaver:Users:fisto:Code Box:Applescript:Automation:Ultimate AI:Queues.scpt" with replacing
	ignoring application responses
		tell application "Ultimate AI Speech Subsystem" to run
	end ignoring
end speakTxt

This is what 1Password does, except that it puts an icon in the menu bar (and has a key combo) to fill in username and password in web forms (and to store all kinds of other info securely as well). If you put its encrypted DB in Dropbox, all your machines are kept in sync. There’s an iPhone/Touch version as well and the app sincs them automatically from the iOS4 version of Dropbox. AgileWebSolutions happens to be a Canadian company, so permit me a bit of chauvinism. :rolleyes:

Having said that, quite an effort on your part.

Don’t you have to pay for 1Password? And 1Password dosen’t integrate with my laptop-wide AI system… :stuck_out_tongue: I must admit, I made this thread primarily as a last-resort backup of the script. If my laptop dies and I have no backup, I can’t log in ANYWHERE.

You do have to pay, and extra for the iPhone version.

What is your “laptop-wide AI system” like?

@ Adam: I don’t have to pay if I make it myself!!! :smiley:

@magikseb: I’m still working on ‘Michelle’ but ‘she’ is going to be made of loads of applescripts. The password is probably the longest so far, but I have a startup script that tells me the time and date, plays spotify, I’m working on weather based on IP geolocation and also Adium integration. Finding what chat sent that last message is freaking impossible, it seems to default to the 1st tab each time. Additionally the system will incorporate a calendar (I dun wanna use iCal because I’m bigheaded) which will set up auto-start ups based on the following day’s appointments and a GUI overlay using quartz composer and Doomsday which can highlight and show info on things… I may publish more parts of her, but she’s very personalised to me so may not suit other people who want to do things differently… And my privacy may be jeopardised. Oh, and to stop scripts talking over each other or having to wait for speech to complete you’ll notice a speech handler at the bottom of the 2nd script that passes speech to her voice module…

Any more code you can share ? Sounds awesome.

I’ll post it as I get parts properly working I guess… Here’s some stuff I used in the auto-start thing:


--set a time to startup

--wakeday is a date to wake
--waketime is in seconds.

--watch for repeated settings

set mon to (month of (wakeday) as number)
set dy to (day of (wakeday))
set yr to characters 3 thru 4 of ((year of (wakeday)) as text)

if dy < 10 then
	set dy to "0" & dy
end if
if mon < 10 then
	set mon to "0" & mon
end if

do shell script ("sudo pmset schedule poweron \"" & mon & "/" & dy & "/" & yr & " " & (round (waketime / 3600) rounding down) & ":" & (round (((waketime / 3600) - (round (waketime / 3600) rounding down)) * 60)) & ":" & 0 & "\"") as text user name "fisto" password "palmz22" with administrator privileges

--open a spotify playlist

--playlistname is the playlist URI

do shell script ("open " & playlistname)


Actually usefull stuff will come as I make it I guess… I think I’ll try make a zipable and configurable version IF
1: I ever finish it
2: I can understand my own code… I’me horrible at commenting.
It will be open-sourced… And I’m off to Uni on the 25th to study A.I. Should get some help there I hope.

@magikseb: http://macscripter.net/viewtopic.php?id=34538 The full system’s post… Getting there!