Home AppleScript & Automation How to Copy-Paste encrypted disk & image passwords in Mac OS X

How to Copy-Paste encrypted disk & image passwords in Mac OS X

3
806

If you like to use long random passwords for things like encrypted disk images (created in Disk Utility) you may have noticed Apple make this rather difficult. Simply put, Apple decided to block the pasting of passwords when creating disk images. Some people suggest this was to make brute force attacks on these encrypted files more difficult, but in reality that doesn’t stand up to reason. Using the command line passwords can be pasted, and it is much easier to launch a brute force attack at the command line level than through a GUI. But I digress.

Typing out long random passwords manually is a pain. This encourages people to use short passwords that are easier to remember and/or type. So the effect of Apple’s move is that it may encourage people to use less secure passwords, all for zero gain. Here’s how to resolve this.

You’ll need to fire up AppleScript Editor. Paste in the following script:

tell application "System Events" to tell process "SecurityAgent" 
    set value of text field 1 of window 1 to (the clipboard)
        if exists (text field 2 of window 1) then 
           set value of text field 2 of window 1 to (the clipboard)
        end if 
        click button 2 of window 1 
end tell

You can remove the second to last line if you don’t want the password dialog to be submitted automatically. The script is designed to handle setting the password when creating a disk image (which requires entering it twice), and the submission of the password when opening the disk image (which only requires entering it once).

Save the script. Next you need to set up a way to trigger and run it easily.

UPDATE: A much better script

UPDATE [March 19, 2015]: Below is an improved script I have pieced together. It has the following features:

  • It will detect and not run if the SecurityAgent isn’t actually running (i.e. you’re not being asked to enter a password by the SecurityAgent).
  • It will actually do the copying of the password from 1Password 5. If you use another password manager, you will need to make the necessary changes to the variable passManager. You may also need to edit the menu commands your password manager uses for copying the password from the current item. See the comments in the script.
  • It will check if you are creating a new password and, if you are, it will let you specify if you wish to save that password to your keychain.
  • … and it has a few other minor bells and whistles that old script didn’t have.
-- Script from best-mac-tips.com

set appName to "SecurityAgent"
set passApp to "1Password 5" (* set this to the name of your password manager *)

tell application "System Events"
	if not (exists window 1 of process appName) then -- test if SecurityAgent window exists
		set answer to display dialog "The password dialog was not found. Please start it again if necessary. 
(This window will close in 5 seconds)" buttons {"Ok"} default button "Ok" giving up after 5
		return -- abort if SecurityAgent window does not exist
	else
		tell application "System Events"
			set position of window 1 of process appName to {20, 250}
			-- move SecurityAgent window out of the way 
		end tell
		display alert "Alert" message "Click OK to initiate copy/paste of password into " & appName & " from " & ¬
			passApp & ", or click Cancel to abort." buttons {"Cancel", "OK"} cancel button "Cancel" default button "OK"
	end if
end tell

tell application "System Events"
	set question to display dialog "Are you creating a new password?" buttons {"No", "Yes"} default button "No"
	set newpass to button returned of question
	if newpass is equal to "Yes" then
		set question to display dialog "Do you wish to store this password in your OS X Keychain?
(since you use " & passApp & ", the chances are you don't want to)" buttons {"No", "Yes"} default button "No"
		set keychainPref to button returned of question
	else
		set keychainPref to "No"
	end if
end tell

tell application "System Events" to set the clipboard to ""

set testResult to ""
repeat until testResult is true
	activate application passApp
	tell application "System Events"
		
		set lengthTest to null
		repeat until lengthTest is equal to true
			set the clipboard to ""
			set passData to ""
			tell application "SystemUIServer"
				if newpass is equal to "No" then
					set answer to display dialog "Make sure correct 1Password item is actively selected (i.e. click it again if it was previously selected, so it is actively highlighted)." & return & return & "Then click 'Continue' to proceed." buttons {"Cancel", "Continue"} cancel button "Cancel" default button "Continue"
				else if newpass is equal to "Yes" then
					set answer to display dialog "Use " & passApp & " to generate a new password. Save the item. Then make sure that new item is actively selected (i.e. click it again after you save it, so it is actively highlighted)." & return & return & "Only then, click 'Continue' to proceed." & return & return & "(Note: You can move this window out of your way if you need to)" buttons {"Cancel", "Continue"} cancel button "Cancel" default button "Continue"
				end if
			end tell
			
			tell process passApp
				(* If you are not using 1Password, you may need to change the menu item clicks, below, to whatever is correct in your particular password manager *)
				click menu item "copy password" of menu "item" of menu bar 1
				delay 0.5 -- Give it a moment to do what it needs to do
				set passData to the clipboard
				set lengthTest to my testPassword(passData)
				if lengthTest is false then
					beep 2
					display dialog "The password is empty, click 'Ok' to try again." & return & return & "Or click 'Cancel' to abort" buttons {"Cancel", "Ok"} cancel button "Cancel" default button "Cancel"
				else if lengthTest is true then
				end if
			end tell
		end repeat
		
		tell application "System Events"
			tell process appName
				set value of text field 1 of window 1 to passData
				
				if exists (text field 2 of window 1) then
					set value of text field 2 of window 1 to passData
				end if
				
				if exists checkbox "Remember password in my keychain" of window 1 then
					if keychainPref is equal to "Yes" then
						if value of checkbox "Remember password in my keychain" of window 1 is 0 then
							click checkbox "Remember password in my keychain" of window 1
						end if
					else if keychainPref is equal to "No" then
						if value of checkbox "Remember password in my keychain" of window 1 is 1 then
							click checkbox "Remember password in my keychain" of window 1
						end if
					end if
					
				else if exists checkbox "Remember this password in my keychain" of window 1 then
					if keychainPref is equal to "Yes" then
						if value of checkbox "Remember this password in my keychain" of window 1 is 0 then
							click checkbox "Remember this password in my keychain" of window 1
						end if
					else if keychainPref is equal to "No" then
						if value of checkbox "Remember this password in my keychain" of window 1 is 1 then
							click checkbox "Remember this password in my keychain" of window 1
						end if
					end if
				end if
				delay 0.5 (* gives  a moment for user to see what's going on *)
				
				if exists button "OK" of window 1 then
					click button "OK" of window 1
				else if exists button "Unlock" of window 1 then
					click button "Unlock" of window 1
				end if
				
				set testResult to my testSuccess(appName)
			end tell
		end tell
	end tell
end repeat

set soundName to "Hero"
display notification "Secure password successfully pasted" with title "Secure Password Paster" sound name soundName

on testSuccess(appName)
	delay 3
	tell application "System Events"
		if not (exists window 1 of process appName) then
			
			display dialog "Password has been pasted. You're all done. 
This window will close in 5 seconds" with title "Process complete" buttons {"OK"} default button "OK" giving up after 5
			return true
			
		else if exists window 1 of process appName then
			set position of window 1 of process appName to {20, 250}
			
			set soundName to "Basso"
			display notification "Password mismatch or error" with title "Secure Password Paster" subtitle "Try again" sound name soundName
			
			display dialog "ERROR: The password is wrong, or doesn't match." & ¬
				return & return & "Click 'Quit' if you wish to abort, or 'Continue' to try again" buttons {"Quit", "Continue"} cancel button "Quit" default button "Continue"
			
			return false
		else
			return "Error"
		end if
	end tell
end testSuccess

on testPassword(passData)
	--	display dialog "passData equals: " & passData
	if the passData is null or the passData is "" then
		return false
	else
		return true
	end if
end testPassword

The simpler script I posted on March 8th, 2015 is below. It’s without all the tricks of the March 15th script, but may suit your needs better if you don’t want so much automation.

-- Script from best-mac-tips.com
set appName to "SecurityAgent"
set passApp to "1Password 5" (* set this to the name of your password manager *)
tell application "System Events"
	if not (exists window 1 of process appName) then -- test if SecurityAgent window exists
		return -- abort if SecurityAgent window does not exist
	end if
end tell
tell application "System Events"
	set position of window 1 of process appName to {10, 10} -- move SecurityAgent window out of the way 
end tell
tell application passApp
	activate -- bring 1Password to the forefront, run it if not running
end tell
tell application "System Events"
	tell application "SystemUIServer"
		set answer to display dialog "Make sure correct 1Password item is actively selected (i.e. click it again if it was previously selected), then click “Continue” to proceed." buttons {"Continue"}
	end tell
	tell process passApp
		(* If you are not using 1Password, you may need to change the menu item clicks, below, to whatever is correct in your particular password manager *)
		click menu item "copy password" of menu "item" of menu bar 1
		delay 1
		set appData to the clipboard
	end tell
	tell application "System Events"
		tell process appName
			set value of text field 1 of window 1 to appData
			if exists (text field 2 of window 1) then
				set value of text field 2 of window 1 to appData
				click button 1 of window 1
			else
				click button 2 of window 1
			end if
		end tell
	end tell
end tell

If you would like to ensure the “Remember password in my keychain” is never ticked, the last TELL statement (tell application “system events”) in the above March 8th script can be changed to this:

tell application "System Events"
	tell process appName
		set value of text field 1 of window 1 to appData
		if exists (text field 2 of window 1) then
			set value of text field 2 of window 1 to appData
			if value of checkbox "Remember password in my keychain" of window 1 is 1 then
				click checkbox "Remember password in my keychain" of window 1
			end if
			set value of checkbox 1 of window 1 to 0
			delay 1 (* gives a moment to see what's going on *)
			click button 1 of window 1
		else
			if value of checkbox "Remember password in my keychain" of window 1 is 1 then
				click checkbox "Remember password in my keychain" of window 1
			end if
			delay 1 (* gives a moment to see what's going on *)
		click button 2 of window 1
	end if
    end tell
end tell

Shortcut to the script

You will also need to tick “Enable access for assistive devices” in the System Preferences. There’s an option for that in Accessibility preferences:

 

Accessibility

You should now be able to copy and paste complex passwords from whatever you use to generate and store your passwords. I use, and highly recommend, a great app called 1Password.

Update for Mavericks and Yosemite

Accessibility options have changed in recent versions of OS X (starting with Mavericks, as far as I can determine). You will need to specifically add your preferred shortcut app to the Accessibility preferences. For instance, you may need to add Alfred, or add Automator. This will depend on which you decide to utilise.

com.apple.preference.security.r

Further Yosemite automation issues:

Further testing on my system indicates Yosemite treats an unsigned script as changed (and therefore as a potential security risk) each time you run it. This makes things complicated for those who wish to through a few scripts in here and there. Because every time you run it you will need to grant it Accessibility permissions.

I know of a few options to work around this. One is to save my script using Script Editor (formally AppleScript Editor) as an application, and you will need to sign it when you do that. That means generating a Certificate Authority in Keychain, and use that to sign your applet. Alternatively, you can follow the information provided by Apple here. That’s the way I recommend going about it. UPDATE: Turns out that info is for Mavericks, and the PLIST file it links to does not exist. I will have to post a solution later. I’ve run out of time on this.

The script provided here on macosxautomation.com might also be useful.

Using an Automator service to run the “paste password” script

You can use Automator to create a system service that will run the script. Once you save that new service, you’ll be able to assign a keyboard shortcut to it using the System Preferences in OS X.

  1. Run Automator.app
  2. Create a new Service
  3. Set the service to receive no input. You’ll find this at the top of the actions pane, “Service receives…”
  4. Add a “Run AppleScript” action
  5. Paste your script into the action (keeping the “on run” and “end run” lines at the beginning and end)
  6. Save the service
  7. Open the System Preferences, and bring up the Keyboard Preferences
  8. Select the Keyboard Shortcuts pane
  9. Select Services in the list on the left.
  10. You should find your new service near the bottom of the list of available services, in the General section. Make sure it is ticked, and add a keyboard shortcut to it (using a key combination that is not likely to be already in use).
You may need to restart your system to get the shortcut to activate.

Using Alfred to run the script

If you have Alfred (with the Powerpack) you can use it to run the above script.

  1. Create a new blank workflow in Alfred
  2. Add in the Trigger called “Hotkey
  3. Assign a hotkey shortcut (something that’s not already in use)
  4. Add in the ActionRun Script
  5. Select script language, “/usr/bin/osascript”
  6. Paste the script (from above) into the script area.
That’s it. Make sure you added Alfred to the Privacy system preferences under Accessibility (see above). You can now use Alfred to paste your password into OS X password fields.

Using Quicksilver

A free alternative to Alfred is Quicksilver. You can use it to run a script also.

Simply create a new Trigger in Quicksilver. Tell it to run the script you created above (you’ll need to locate the script in the folder you saved it to).

Edit the Trigger and set a hotkey.

Make sure you added Quicksilver to the Privacy system preferences under Accessibility (see above).

Using Fastscripts

Another great way to run scripts, via shortcuts, is the app called FastScripts. For loading in up to ten shortcuts it is free. It’s around $10 if you need more.

Using the command line instead of a script

You can also use the command line (via Terminal.app) to mount your disk image. Here’s the command to use:

hdiutil attach /path/to/imagefile -stdinpass

If the image file has a long path, you can simply type in hdiutil attach and then drag the file from finder into the Terminal. Then add -stdinpass and hit Return.

You can also use the command line for creating an encrypted disk image, and doing it this way will allow you to paste your password in.

Use these commands:

cd /path/to/where/you/want/the/image
hdiutil create -size thesize -encryption -type SPARSEBUNDLE -fs HFS+ thename

You’ll need to replace “thesize” and “thename”. The size is the maximum size of the sparsebundle. It won’t take up this amount of space until you actually add that amount of data into the image, but this will determine the maximum amount of space it is allowed to take. The name is just the name of the image file. The actual volume inside the image you can name from within Finder, once you’ve mounted the image.

When doing the cd command, if the path is a long one, remember you can drag the folder from Finder into the terminal, and the path will automagically appear.

3 Comments

    • Hi Jake. I’ve not installed Yosemite yet. Will likely be a few months before I do. So I may not get around to looking for a solution to this until then. If you find one yourself, please post it here. Cheers… Jonathan

Leave A Reply

Please enter your comment!
Please enter your name here