Random Password Generator

I’m a bit of a rookie when it comes to AppleScript and I could do with a hand, if anyone can help please?

I’m trying to write a fairly simple script (to be turned into an app) to generate random passwords for a NGO that I’m working with.

So far I have this …

set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':"|,.<>/?`~"*
set thePassword to “”
repeat (12) times
set randomCharacter to some character of theCharacters
set thePassword to thePassword & randomCharacter
end repeat
return thePassword

Things I really want to change …

When people run the script ideally I want to make initially open up a dialogue box giving users the ability to set the password length (with a 12 character default minimum) and a button say something like, “Generate”.

I want to set the number of numbers and special characters into the password to something like one of each for a 12 character password, 2 of each for 13-23 character passwords, 3 of each for 24-34 character passwords and 4 of each for any password that has 35-50 characters.

When they hit this button it needs to take them through to a further dialogue box showing the password and three buttons - copy password and quit, copy and generate another password, quit.

I’m fairly certain I know how to get the dialogue boxes to appear because I’ve done scripts with these in them before …

display dialog “Thanks for your donation. I really do genuinely appreciate it.” buttons ¬
{“Quit”, “Thanks!”} ¬
default button “Thanks!”

… but the setting the numbers and characters bit is really throwing me.

Can anyone help please?

Hi.

You can include a default answer parameter with display dialog, which will add a field in which the user can enter text, eg.:

repeat
	set numberOfCharacters to text returned of ¬
		(display dialog "How many characters would you like in the password?" default answer "12")
	try
		set numberOfCharacters to numberOfCharacters as integer
		exit repeat
	on error
		display dialog "The text entered must be a number!"
	end try
end repeat

repeat numberOfCharacters times

	-- Your password building code here

end repeat

If you’d prefer the field to be empty, just pass an empty string as the default answer parameter.

By the way, you can post AppleScript code on this site by placing three backticks on separate lines above and below it. This’ll put an “Open in Script Editor” button below it as in my script above:

```
Some AppleScript code
```

Thanks Nigel, that’s really helpful. So the script now looks like this (couldn’t work out how to get the AppleScript thing to work in the post, sorry)

set r to return
display dialog “Random Password generator” & r & r & “A small application to quickly and easily generated random secure passwords” buttons ¬
{“Not Now”, “Let’s make a password”} ¬
default button “Let’s make a password”
if (button returned of the result is “Not Now”) then error number -128 – “User canceled” [sic]
set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':"|,.<>/?`~"*
set thePassword to “”
repeat (12) times
set randomCharacter to some character of theCharacters
set thePassword to thePassword & randomCharacter
repeat
set numberOfCharacters to text returned of ¬
(display dialog “Password Rules” & r & r & “All passwords must have at least 12 characters, so how many characters would you like?” default answer “12”)
try
set numberOfCharacters to numberOfCharacters as integer
exit repeat
on error
display dialog “The text entered must be a number!”
end try
end repeat
repeat numberOfCharacters times
– Your password building code here
end repeat
return thePassword
end repeat

But there’s something screwy now because I’m not sure it’s actually generating a password. Plus how do I get the result to display in a box with the buttons I mention above (copy password and quit, copy and generate another password, quit.)

Hi Cloudwalker_3. Here’s your script rearranged into working order. I don’t know what you want to do with the password once it’s created. The code here both displays it and returns it:

set r to return
display dialog "Random Password generator" & r & r & "A small application to quickly and easily generated random secure passwords" buttons ¬
	{"Not Now", "Let’s make a password"} ¬
		default button "Let’s make a password"
if (button returned of the result is "Not Now") then error number -128 --"User canceled" [sic]
set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':\"|,.<>/?`~*"
set thePassword to ""

repeat
	set numberOfCharacters to text returned of ¬
		(display dialog "Password Rules" & r & r & "All passwords must have at least 12 characters, so how many characters would you like?" default answer "12")
	try
		set numberOfCharacters to numberOfCharacters as integer
		exit repeat
	on error
		display dialog "The text entered must be a number!"
	end try
end repeat

repeat (numberOfCharacters) times
	set randomCharacter to some character of theCharacters
	set thePassword to thePassword & randomCharacter
end repeat

display dialog thePassword

return thePassword
1 Like

I’ve included a suggestion below which meets the above requirement. The password is not random in that it includes a specific number of lowercase and uppercase letters, numbers, and special characters. The script takes 3 milliseconds on my computer to generate a 24-character password.

set thePassword to getPassword(12)

on getPassword(passwordLength)
	set nonLetterCount to (passwordLength div 12) + 1 -- modify as desired
	if passwordLength mod 12 = 0 then set nonLetterCount to nonLetterCount - 1
	set lowercaseLetterCount to (passwordLength - (nonLetterCount * 2)) div 2
	copy lowercaseLetterCount to uppercaseLetterCount
	if passwordLength mod 2 ≠ 0 then set uppercaseLetterCount to uppercaseLetterCount + 1
	set lowercaseLetters to "abcdefghijklmnopqrstuvwxyz"
	set lowercaseLetters to makeRandom(lowercaseLetters, lowercaseLetterCount)
	set uppercaseLetters to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	set uppercaseLetters to makeRandom(uppercaseLetters, uppercaseLetterCount)
	set theNumbers to "0123456789"
	set theNumbers to makeRandom(theNumbers, nonLetterCount)
	set theSpecialCharacters to "!@#$%^&()_±=[]{};':|,.<>/?`~*"
	set theSpecialCharacters to makeRandom(theSpecialCharacters, nonLetterCount)
	set thePassword to lowercaseLetters & uppercaseLetters & theNumbers & theSpecialCharacters
	set thePassword to shuffleList(thePassword)
	return thePassword
end getPassword

on makeRandom(theString, theCount)
	set randomString to ""
	repeat theCount times
		set randomCharacter to some character of theString
		set randomString to randomString & randomCharacter
	end repeat
	return randomString
end makeRandom

on shuffleList(theString) -- from Nigel
	set theList to characters of theString
	repeat with i from (count of theList) to 2 by -1
		set j to random number from 1 to i
		if i ≠ j then
			set temp to item i of theList
			set item i of theList to item j of theList
			set item j of theList to temp
		end if
	end repeat
	return theList as text
end shuffleList
1 Like

So this is where I am now …

set r to return

display dialog "Random Password generator" & r & r & "A small Applescript app to quickly and easily" & r & "generate random and secure secure passwords." & r & r & "Passwords are compliant with the current" & r & "BYM IT security guidelines, specifically:" & r & r & "1. At least 12 characters." & r & "2. One or more upper case letters." & r & "3. One or more numbers. " & r & "4. One or more special characters." & r & "." buttons ¬
	{"Not now", "Okay, let's make one!"} ¬
		default button "Okay, let's make one!"
if (button returned of the result is "Not now") then error number -128

set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':\"|,.<>/?`~*"
set thePassword to ""
repeat
	set numberOfCharacters to text returned of ¬
		(display dialog "Password Rules" & r & r & "All passwords must have at least 12 characters, so how many characters would you like?" default answer "12")
	try
		set numberOfCharacters to numberOfCharacters as integer
		exit repeat
	on error
		display dialog "The text entered must be a number!"
	end try
end repeat

repeat (numberOfCharacters) times
	set randomCharacter to some character of theCharacters
	set thePassword to thePassword & randomCharacter
end repeat

set nextAction to button returned of (display dialog thePassword buttons {"Make another password", "Copy to clipboard and quit"} default button "Copy to clipboard and quit")
set the clipboard to thePassword
if (nextAction is "Quit") then exit repeat
if (button returned of the result is "Quit") then error number -128 --"User canceled" [sic]
set r to return
display dialog "I hope you found this script useful - coding Applescript and creating useful mini apps like this is one of the fun things I do when not crayon wrangling. " & r & r & "Have a great day, and remember, in a world where you can be anything, be kind." buttons ¬
	{"Quit", "Thanks"} ¬
		default button "Thanks"
if (button returned of the result is "Quit") then error number -128 -- "User canceled" [sic]
set r to return
display dialog "You're awesome!" buttons ¬
	{"Quit", "Also Quit"} ¬
		default button "Also Quit"
if (button returned of the result is "Quit") then error number -128 -- "User canceled" [sic]

Problems:

  1. I’ve obviously cocked the script up somehow because when you press the 'Copy to clipboard and quit" button it ought to take you to the next dialog box but instead I get an error message saying < The variable result is not defined. > it does copy it to the clipboard though so that bit IS working.

  2. I really want to customise the buttons that appear on the password length dialogue box but I can’t work out how the get the right code in there.

Any help will be very gratefully received!

set r to return

repeat -- until the user clicks a "stop"-related button in a dialog.
	display dialog "Random Password generator" & r & r & "A small Applescript app to quickly and easily" & r & "generate random and secure secure passwords." & r & r & "Passwords are compliant with the current" & r & "BYM IT security guidelines, specifically:" & r & r & "1. At least 12 characters." & r & "2. One or more upper case letters." & r & "3. One or more numbers. " & r & "4. One or more special characters." & r & "." buttons ¬
		{"Not now", "Okay, let's make one!"} ¬
			default button "Okay, let's make one!" cancel button "Not now"
	
	set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':\"|,.<>/?`~*"
	set thePassword to ""
	repeat -- until a satisfactory number input's obtained.
		set numberOfCharacters to text returned of ¬
			(display dialog "Password Rules" & r & r & "All passwords must have at least 12 characters, so how many characters would you like?" default answer "12")
		try
			set numberOfCharacters to numberOfCharacters as integer
			if (numberOfCharacters < 12) then error
			exit repeat
		on error
			display dialog "The text entered must be a number greater than or equal to 12!"
		end try
	end repeat
	
	-- Build a password from the allowed characters.
	repeat (numberOfCharacters) times
		set randomCharacter to some character of theCharacters
		set thePassword to thePassword & randomCharacter
	end repeat
	
	-- Check it for conformity to the guidelines.
	set checks to {lowercase:0, uppercase:0, digits:0, specials:0}
	repeat with thisID in (thePassword's id)
		if ((thisID ≥ "a"'s id) and (thisID ≤ "z"'s id)) then
			set checks's lowercase to (checks's lowercase) + 1
		else if ((thisID ≥ "A"'s id) and (thisID ≤ "Z"'s id)) then
			set checks's uppercase to (checks's uppercase) + 1
		else if ((thisID ≥ "0"'s id) and (thisID ≤ "9"'s id)) then
			set checks's digits to (checks's digits) + 1
		else
			set checks's specials to (checks's specials) + 1
		end if
	end repeat
	set passwordOK to ((checks's uppercase > 0) and (checks's digits > 0) and (checks's specials > 0))
	
	-- Display the password and the conformity verdict.
	set message to thePassword & item (((passwordOK) as integer) + 1) of {" (Doesn't comply with guidelines)", " (Password OK)"}
	set nextAction to button returned of (display dialog message buttons {"Make another password", "Copy to clipboard and quit"} default button "Copy to clipboard and quit")
	if (nextAction is "Copy to clipboard and quit") then
		set the clipboard to thePassword
		exit repeat -- This jumps out of the repeat rather than actually stopping the script.
	end if
end repeat

display dialog "I hope you found this script useful - coding Applescript and creating useful mini apps like this is one of the fun things I do when not crayon wrangling. Thanks to the folks at macscripter.net for all their help with this one!" & r & r & "Have a great day, and remember, in a world where you can be anything, be kind." buttons ¬
	{"Quit", "Thanks"} ¬
		default button "Thanks" cancel button "Quit"
display dialog "You're awesome!" buttons ¬
	{"Quit", "Also Quit"} ¬
		default button "Also Quit"
-- The script finishes here anyway. No need for a quit option unless there's more to come.
1 Like

You’re a total star Nigel! Just out of interest, if I wanted to kill off the < (password OK) > text, but keep in the < (Doesn’t comply with guidelines) > what would I need to change?

Hi @Cloudwalker_3.

I’ve changed the conformity test code in post 9 above as I realised that the uppercase, digits, and specials counts each need to be checked, not just summed to see if there are three instances between them. This led to the discovery that the considering case condition wasn’t working for some reason. (I’ve no idea why!) The code now checks each character’s id instead.

Two possibilities:

	set message to thePassword & item (((passwordOK) as integer) + 1) of {" (Doesn't comply with guidelines)", ""}

or:

	set message to password
	if not (passwordOK) then set message to thePassword & " (Doesn't comply with guidelines)"
1 Like

The second version of that seems to work well.

There was a bit of code in an earlier version that dealt with people inadvertently putting in letters …

on error

display dialog "The text entered must be a number!"

end try

end repeat

Where should I slot that in?

I’ll definitely keep the MacScripter bit by the way, credit where credit is due. Couldn’t have got here without you guys.

FWIW, a minor revision of Nigel’s code avoids a non-conforming password (which may be good or bad). The timing result with a 12-character password was one millisecond.

set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':\"|,.<>/?`~*"
repeat 100 times -- or simply repeat
	set thePassword to getPassword(theCharacters, 12)
	if checkPassword(thePassword) is true then exit repeat
end repeat
thePassword

on getPassword(theCharacters, numberOfCharacters)
	set thePassword to ""
	repeat (numberOfCharacters) times
		set randomCharacter to some character of theCharacters
		set thePassword to thePassword & randomCharacter
	end repeat
	return thePassword
end getPassword

on checkPassword(thePassword)
	set checks to {lowercase:0, uppercase:0, digits:0, specials:0}
	repeat with thisID in (thePassword's id)
		if ((thisID ≥ "a"'s id) and (thisID ≤ "z"'s id)) then
			set checks's lowercase to (checks's lowercase) + 1
		else if ((thisID ≥ "A"'s id) and (thisID ≤ "Z"'s id)) then
			set checks's uppercase to (checks's uppercase) + 1
		else if ((thisID ≥ "0"'s id) and (thisID ≤ "9"'s id)) then
			set checks's digits to (checks's digits) + 1
		else
			set checks's specials to (checks's specials) + 1
		end if
	end repeat
	set passwordOK to ((checks's uppercase > 0) and (checks's digits > 0) and (checks's specials > 0))
	return passwordOK
end checkPassword

It’s still there, but has been extended to cover people entering numbers less than 12 too. In the try … on error … end try block, the line which turns the text numberOfCharacters into an integer errors if that operation can’t be done — ie. the characters in the text don’t all represent number characters. The error causes a jump to the dialog in the on error section. If that error doesn’t occur, but the integer turns out to be less than 12, an error’s thrown deliberately, with the same effect. If neither error occurs, the exit repeat is executed.

1 Like

@Nigel_Garvey: If I wanted to kill off the < (password OK) > text, but keep in the < (Doesn’t comply with guidelines) > what would I need to change?

If it definitely needs to be in there it’s possible okay but I’d need it to be on a separate line in the dialogue box because at the moment some passwords cause it to be right next to the actual displayed password which is a bit confusing.

Out of interest @peavine, if I was going to put that section of code in where does it fit? I can find the start of where it inserts but can’t work out what I need to leave in.

If it’s helpful here’s the full script at the moment …

set r to return

repeat -- until the user clicks a terminating button in a dialog.
	display dialog "Random Password generator" & r & r & "A small Applescript app to quickly and easily" & r & "generate random and secure secure passwords." & r & r & "Passwords are compliant with the current" & r & "BYM IT security guidelines, specifically:" & r & r & "1. At least 12 characters." & r & "2. One or more upper case letters." & r & "3. One or more numbers. " & r & "4. One or more special characters." & r & "." buttons ¬
		{"Not now", "Okay, let's make one!"} ¬
			default button "Okay, let's make one!" cancel button "Not now"
	
	set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':\"|,.<>/?`~*"
	set thePassword to ""
	repeat -- until a satisfactory number input's obtained.
		set numberOfCharacters to text returned of ¬
			(display dialog "Password Rules" & r & r & "All passwords must have at least 12 characters, so how many characters would you like?" default answer "12")
		try
			set numberOfCharacters to numberOfCharacters as integer
			if (numberOfCharacters < 12) then error
			exit repeat
		on error
			display dialog "The password must have at least 12 characters in it to be compliant with the current BYM IT security guidelines"
		end try
	end repeat
	
	-- Build a password from the allowed characters.
	repeat (numberOfCharacters) times
		set randomCharacter to some character of theCharacters
		set thePassword to thePassword & randomCharacter
	end repeat
	
	-- Check it for conformity to the guidelines.
	set checks to {lowercase:0, uppercase:0, digits:0, specials:0}
	considering case
		repeat with thisCharacter in thePassword
			if (thisCharacter ≥ "a" and thisCharacter ≤ "z") then
				set checks's lowercase to (checks's lowercase) + 1
			else if (thisCharacter ≥ "A" and thisCharacter ≤ "Z") then
				set checks's uppercase to (checks's uppercase) + 1
			else if (thisCharacter ≥ "0" and thisCharacter ≤ "9") then
				set checks's digits to (checks's digits) + 1
			else
				set checks's specials to (checks's specials) + 1
			end if
		end repeat
	end considering
	set passwordOK to ((checks's uppercase) + (checks's digits) + (checks's specials) ≥ 3)
	
	-- Display the password and the conformity verdict.
	set message to thePassword & item (((passwordOK) as integer) + 1) of {" (Doesn't comply with guidelines)", "This password is good to go"}
	set nextAction to button returned of (display dialog message buttons {"Make another password", "Copy to clipboard and quit"} default button "Copy to clipboard and quit")
	if (nextAction is "Copy to clipboard and quit") then
		set the clipboard to thePassword
		exit repeat -- This jumps out of the repeat rather than actually stopping the script.
	end if
end repeat

display dialog "I hope you found this script useful - coding Applescript and creating useful mini apps like this is one of the fun things I do when not crayon wrangling." & r & r & "Some thanks do need to go to the guys on MacScripter.net for their help with this one though because it was a bit pesky." & r & r & "Have a great day, and remember, in a world where you can be anything, be kind." buttons ¬
	{"Quit", "Thanks"} ¬
		default button "Thanks" cancel button "Quit"
display dialog "You're awesome!" buttons ¬
	{"Quit", "Also Quit"} ¬
		default button "Also Quit"
-- The script finishes here anyway. No need for a quit option unless there's more to come.

I inserted the new code and changed the dialog message to a generic one. BTW, I wonder why the security guidelines you cite don’t require a lowercase letter?

set r to return

repeat -- until the user clicks a terminating button in a dialog.
	display dialog "Random Password generator" & r & r & "A small Applescript app to quickly and easily" & r & "generate random and secure secure passwords." & r & r & "Passwords are compliant with the current" & r & "BYM IT security guidelines, specifically:" & r & r & "1. At least 12 characters." & r & "2. One or more upper case letters." & r & "3. One or more numbers. " & r & "4. One or more special characters." & r & "." buttons ¬
		{"Not now", "Okay, let's make one!"} ¬
			default button "Okay, let's make one!" cancel button "Not now"
	
	repeat -- until a satisfactory number input's obtained.
		set numberOfCharacters to text returned of ¬
			(display dialog "Password Rules" & r & r & "All passwords must have at least 12 characters, so how many characters would you like?" default answer "12")
		try
			set numberOfCharacters to numberOfCharacters as integer
			if (numberOfCharacters < 12) then error
			exit repeat
		on error
			display dialog "The password must have at least 12 characters in it to be compliant with the current BYM IT security guidelines"
		end try
	end repeat
	
	set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':\"|,.<>/?`~*"
	repeat 100 times -- or simply repeat
		set thePassword to getPassword(theCharacters, numberOfCharacters)
		if checkPassword(thePassword) is true then exit repeat
	end repeat
	
	-- Display the password and the conformity verdict.
	set message to "The password is " & thePassword
	set nextAction to button returned of (display dialog message buttons {"Make another password", "Copy to clipboard and quit"} default button "Copy to clipboard and quit")
	if (nextAction is "Copy to clipboard and quit") then
		set the clipboard to thePassword
		exit repeat -- This jumps out of the repeat rather than actually stopping the script.
	end if
end repeat

display dialog "I hope you found this script useful - coding Applescript and creating useful mini apps like this is one of the fun things I do when not crayon wrangling." & r & r & "Some thanks do need to go to the guys on MacScripter.net for their help with this one though because it was a bit pesky." & r & r & "Have a great day, and remember, in a world where you can be anything, be kind." buttons ¬
	{"Quit", "Thanks"} ¬
		default button "Thanks" cancel button "Quit"
display dialog "You're awesome!" buttons ¬
	{"Quit", "Also Quit"} ¬
		default button "Also Quit"
-- The script finishes here anyway. No need for a quit option unless there's more to come.

on getPassword(theCharacters, numberOfCharacters)
	set thePassword to ""
	repeat (numberOfCharacters) times
		set randomCharacter to some character of theCharacters
		set thePassword to thePassword & randomCharacter
	end repeat
	return thePassword
end getPassword

on checkPassword(thePassword)
	set checks to {lowercase:0, uppercase:0, digits:0, specials:0}
	repeat with thisID in (thePassword's id)
		if ((thisID ≥ "a"'s id) and (thisID ≤ "z"'s id)) then
			set checks's lowercase to (checks's lowercase) + 1
		else if ((thisID ≥ "A"'s id) and (thisID ≤ "Z"'s id)) then
			set checks's uppercase to (checks's uppercase) + 1
		else if ((thisID ≥ "0"'s id) and (thisID ≤ "9"'s id)) then
			set checks's digits to (checks's digits) + 1
		else
			set checks's specials to (checks's specials) + 1
		end if
	end repeat
	set passwordOK to {(checks's uppercase > 0) and (checks's digits > 0) and (checks's specials > 0)}
	return passwordOK
end checkPassword

I’m not sure if this is the correct way to do it. But I do believe its also possible to use
NSUUID class to make random id to be used as password.

use framework "Foundation"
use scripting additions

set theUUID to current application's NSUUID's UUID()
return (theUUID's UUIDString()) as string

But on other hand, I guess it will be easy to do brute force to get its password.

I tested this on Monterey and also received unexpected results. The issue appears only to be with the greater- and less-than operators.

"a" = "a" --> true
"a" = "A" --> true
"A" < "z" --> true
"z" > "A" --> true

considering case
	"a" = "a" --> true
	"a" = "A" --> false - considering case works
	"A" < "z" --> true - unexpected result
	"z" > "A" --> true - unexpected result
end considering

For what it’s worth guys, I think I have this one cracked now.

Here’s the final code

-- Random Password Generator Script
-- A script that generates a random password and copies it to the clipboard for later use.

-- The first part of the script opens up a dialog box with the name of the script, an explanation of what it does - with two buttons.
-- The 'Not now' button quits the script
-- The 'Okay, let's make one!' button takes the user to the next stage.

set r to return
repeat
	display dialog "A small Applescript app to quickly and easily" & r & "generate random and secure secure passwords." & r & r & "Current password creation best practice is that," & r & "in terms of complexity, all passwords should have:" & r & r & "1. A minimum of 12 characters." & r & "2. One or more upper case letters." & r & "3. One or more numbers. " & r & "4. One or more special characters." buttons ¬
		{"Not now", "Let's make a password!"} ¬
			default button "Let's make a password!" cancel button "Not now"
	repeat
		
		-- The next part of the script's code opens up the password length dialog box, which asks the user to input a number for the length of password that they want to generate (with a default of 12 already entered) - with two buttons.
		-- The 'Cancel' button quits the script.
		-- The 'OK' button takes the user to the next stage.
		
		set numberOfCharacters to text returned of ¬
			(display dialog "Password Rules" & r & r & "Based on the principle that strong passwords need at least" & r & "12 characters in them, how many characters would you like?" default answer "12") & r
		try
			set numberOfCharacters to numberOfCharacters as integer
			
			-- The next part of the script's code deals with users putting in numbers smaller than 12 in the previous password length dialog box. If they do do this, the code below makes a dialog box appear with a warning message about password length - with two buttons.
			-- The 'Cancel' button quits the script
			-- The 'OK' button restarts the script.
			
			if (numberOfCharacters < 12) then error
			exit repeat
		on error
			display dialog "Passwords should have at least 12 characters in them to be secure. Please re-enter the number" & r & "of characters you'd like in your password." with icon stop
		end try
	end repeat
	
	-- The code below is the character set that the password generator draws it's random characters from.
	-- The exact password coding formula is at the end of the script
	
	set theCharacters to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&()_±=[]{};':\"|,.<>/?`~*"
	repeat 100 times -- or simply repeat
		set thePassword to getPassword(theCharacters, numberOfCharacters)
		if checkPassword(thePassword) is true then exit repeat
	end repeat
	
	-- The script's code now opens up a dialog box showing the password that has just been generated (which can be copied from the dialog box if necessary) - with two buttons.
	-- The 'Make another password' button wipes the password and restarts the script.
	-- The 'Copy to clipboard and quit' button copies the password to the clipboard and then begins the quit process.
	
	set message to "Your new password is:   " & r & r & thePassword & r
	set nextAction to button returned of (display dialog message buttons {"Make another password", "Copy to clipboard and quit"} default button "Copy to clipboard and quit")
	if (nextAction is "Copy to clipboard and quit") then
		set the clipboard to thePassword
		exit repeat -- This instruction means that the script jumps out of the repeat rather than actually stopping.
	end if
end repeat

-- The script finishes here.

-- This last bit of Applescript code below is the code that controls the complexity of the passwords and is used by the generator code above.

on getPassword(theCharacters, numberOfCharacters)
	set thePassword to ""
	repeat (numberOfCharacters) times
		set randomCharacter to some character of theCharacters
		set thePassword to thePassword & randomCharacter
	end repeat
	return thePassword
end getPassword

on checkPassword(thePassword)
	set checks to {lowercase:0, uppercase:0, digits:0, specials:0}
	repeat with thisID in (thePassword's id)
		if ((thisID ≥ "a"'s id) and (thisID ≤ "z"'s id)) then
			set checks's lowercase to (checks's lowercase) + 1
		else if ((thisID ≥ "A"'s id) and (thisID ≤ "Z"'s id)) then
			set checks's uppercase to (checks's uppercase) + 1
		else if ((thisID ≥ "0"'s id) and (thisID ≤ "9"'s id)) then
			set checks's digits to (checks's digits) + 1
		else
			set checks's specials to (checks's specials) + 1
		end if
	end repeat
	set passwordOK to ((checks's uppercase > 0) and (checks's digits > 0) and (checks's specials > 0))
	return passwordOK
end checkPassword

-- End of code

Special thanks for to @Nigel_Garvey and @peavine because without their help I wouldn’t have got there.

3 Likes
set LengthList to {"L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9", "L10", "L11", "L12", "L13", "L14", "L15", "L16", "L17", "L18", "L19", "L20"}
set NumList to {"N0", "N1", "N2", "N3", "N4", "N5", "N6", "N7", "N8", "N9"}
set SpecList to {"S0", "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9"}




set answer to choose from list LengthList & NumList & SpecList with prompt "Set Up Password Parameters: 
L for Length
N for Numeric Characters
S for Special Characters" with title "Password Information Input" with multiple selections allowed




if answer is not false then
	set i to count of answer
	
	if (i = 3) then
		if (((item 1 of answer) contains "L") and ((item 2 of answer) contains "N") and ((item 3 of answer) contains "S")) then
			
			set PLength to ((characters 2 thru -1 of (item 1 of answer)) as string)
			
			set PNum to ((characters 2 thru -1 of (item 2 of answer)) as string)
			
			set PSpec to ((characters 2 thru -1 of (item 3 of answer)) as string)
			
			
			set aLength to PLength as number
			set NNum to PNum as number
			set NSpec to PSpec as number
		else
			display dialog "You must select one of each parameter for password:  Length, Numeric Characters, and Special Characters" with icon file (POSIX file "/Users/dracon/Documents/Misc Graphics/Icons/Icon Fix Mojave/Password/Password Maker.png") with title "Error!"
			return
		end if
	else
		display dialog "You must select 3 parameters." with icon file (POSIX file "/Users/dracon/Documents/Misc Graphics/Icons/Icon Fix Mojave/Password/Password Maker.png") with title "Error!"
		return
	end if
else
	display dialog "This is really crappy input." with icon file (POSIX file "/Users/dracon/Documents/Misc Graphics/Icons/Icon Fix Mojave/Password/Password Maker.png") with title "Error!"
	return
end if



set Pass to GenerateRandom(aLength, NNum, NSpec)
display dialog Pass & "

OK copies to clipboard." with icon file (POSIX file "/Users/dracon/Documents/Misc Graphics/Icons/Icon Fix Mojave/Password/Password Maker.png") with title "Your Password"
set the clipboard to Pass




on GenerateRandom(aLength, NNum, NSpec)
	
	set ie to NNum + NSpec
	if ((ie is greater than aLength) or (aLength is less than 1)) then
		display dialog "Total of Special and Numerical Characters Exceeds String Length or Other Crap Problems!" with icon file (POSIX file "/Users/dracon/Documents/Misc Graphics/Icons/Icon Fix Mojave/Password/Password Maker.png") with title "Error!"
		error number -128 (* user cancelled *)
	end if
	
	set ie to aLength
	if (ie is greater than 20) then
		display dialog "String Length Exceeds 20 Characters!" with icon file (POSIX file "/Users/dracon/Documents/Misc Graphics/Icons/Icon Fix Mojave/Password/Password Maker.png") with title "Error!"
		error number -128 (* user cancelled *)
	end if
	
	set PFrame to {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
	
	set AlphaChars 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", "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 NumChars to {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}
	set SpecChars to {"!", "@", "#", "$", "%", "^", "&", "*", "(", ")"}
	set aString to ""
	
	
	
	(*
===========================================================
*)
	
	if (NNum is not equal to 0) then
		set cNum to 0
		set nstop to 0
		repeat until (cNum is not less than NNum)
			set nstop to nstop + 1
			if (nstop is greater than (NNum + 10)) then exit repeat
			set a to (random number from 1 to aLength)
			if (item {a} of PFrame is 1) then
				set item {a} of PFrame to 2
				set cNum to cNum + 1
			end if
		end repeat
	end if
	
	(*
==============================================================
*)
	
	if (NSpec is not equal to 0) then
		set cNum to 0
		set nstop to 0
		repeat until (cNum is not less than NSpec)
			set nstop to nstop + 1
			if (nstop is greater than (NSpec + 10)) then exit repeat
			set a to (random number from 1 to aLength)
			if (item {a} of PFrame is 1) then
				set item {a} of PFrame to 3
				set cNum to cNum + 1
			end if
		end repeat
	end if
	
	
	(*
==================================================================	
*)
	
	
	set a to 1
	repeat aLength times
		if (item {a} of PFrame = 2) then
			set b to (random number from 1 to 10)
			set aString to aString & item {b} of NumChars
		else
			if (item {a} of PFrame = 3) then
				set b to (random number from 1 to 10)
				set aString to aString & item {b} of SpecChars
			else
				set b to (random number from 1 to 52)
				set aString to aString & item {b} of AlphaChars
			end if
		end if
		set a to a + 1
	end repeat
	
	
	(*
==============================================================
*)
	
	
	return aString
end GenerateRandom

Sorry I messed up the post - not used to the new site.