Google Checkout Development Setup Without Superflous SSL Certificates
One of the nicest feature of Os X is the Keychain. The Keychain allows you to store passwords (and arbitrary text) in password protected, encrypted files.
The Keychain is used by the Os X stock applications like Safari and Mail.app but also third party programs like Cyberduck use it to store the entered passwords in the Keychain instead of rolling their own secure password storage system. I would even consider Keychain support to be an essential feature for sufficient Os X integration.
Mac Os X provides a straight API to the Keychain Service for C, Objective C and Java. Swell! What happens if there is not wrapper for your favourite programming language? For example, I could not find wrappers for Python or Ruby via Google1.
Hm, what other programming language do I use regularly? The Shell! After all, Os X is based on BSD and provides equivalents to a lot of its UI tools as simple command line programs. The program we are searching for is known as security (man security yields a good documentation).
Creating a Keychain
We should create a new key chain for our experiments so we do not damage existing passwords. You can create a new key chain called Keys with the following command:
$> security create-keychain -P Keys.keychain
Note that you have to provide the file extension .keychain. The parameter -P will make the SecurityAgent service ask you for the password fo rthis keychain. The new keychain will be available as ~/Library/Keychains/Keys.keychain.
After creating the key chain we can open Keychain Access.app in /Applications/Utilities and add our key chain to it by selecting “Edit” > “Keychain List” in the main Menu.
Afterwards, we will see the keys - none at the moment - in our key chain.
Writing a Password
What’s next? Well, let’s add a password to the key chain:
$> security add-generic-password -a manuel -s example.com \
-p password Keys.keychain
This will add a new password for the user manuel with the service example.com to the key chain Keys.keychain. If you do not specify a key chain then the password will be added your login key chain.
Note that specifying the password on the command line propably is not a very good idea since it will be visible to every user via ps ax while it is running. There currently is no way to make security prompt for the password so propably the best idea is to set the password using the Keychain Access.app again.
Reading a Password
Reading a password is propably the most oftenly used action - you will only want to set passwords once. Passwords are seemingly retrieved with the find-generic-password command:
$> security find-generic-password -a manuel -s example.com Keys.keychain
If you execute this command then you will get the following output:
keychain: "/Users/manuel/Library/Keychains/Keys.keychain" class: "genp" attributes: ...
Well, this is pretty uninteresting. We wanted the password! So we read up the manual of security once more and see that we have to specify the -g password to make security print the actual password. So, let’s try it again. When entering
$> security find-generic-password -g -a manuel \
-s example.com Keys.keychain
then a window will pop up and ask us for the password of our key chain. After entering the password, we will get the following output:
keychain: "/Users/manuel/Library/Keychains/Keys.keychain" class: "genp" attributes: ... password: "password"
As we find out here, the last line is written to stderr (what the hack?) and the rest is written to stdout. So we tell bash to redirect the output of the stderr to a copy of the stdout file handle and redirect the old stdout to /dev/null (note that the order of the 2>&1 and >/dev/null is important):
$> security 2>&1 >/dev/null find-generic-password -g \
-a manuel -s example.com Keys.keychain
We are only interested in the password so pipe the output through sed and put the whole stuff into a bash function:
get_password () {
security 2>&1 >/dev/null find-generic-password -g \
-a manuel -s example.com Keys.keychain \
| sed 's/password: "\(.*\)"/\1/'
}
So the next time we need a password, we can simply use $(get_password) to get it from the keychain. For example:
#!/bin/sh
get_password () {
security 2>&1 >/dev/null find-generic-password -g \
-a manuel -s example.com Keys.keychain \
| sed 's/password: "\(.*\)"/\1/'
}
# We said passing passwords on the command line was bad above. We
# only do this here for the sake of a simple example.
wget --user=manuel --password=$(get_password) http://example.com
This is part 1 of 2. The second part deals with how to integrate the Keychain into your Ruby application (and shows how to do this with Capistrano). I will publish the second part soon.
1 Of course there are Cocoa bindings for Python and Ruby but aren’t those a bit heavyweight for using so simple as the Keychain Service?

June 5th, 2010 at 1:05 am
Thank you for your help!