Social Media
GitHub
Navigation
Powered by Squarespace
« 360iDev Conference Notes, or How I Spent my September Vacation | Main | Not Feeling Entitled So Far (Sandbox or Dropbox, Pick Only One) »
Saturday
Sep032011

Steal This Code and Protect Their Data: Simplifying KeyChain Access

Invalidname Meet iPhone Explorer Invalidname Learn Keychain Noel Llopis Keychain is Obtuse

 

 

The Code

The last couple of months, I've been working on my first Mac App (more on that in a later post).  As part of this App, I'm calling a REST API that requires that I have the user's password for that service to use in the API calls.  Although that API is a minor part of the App, and although the service doesn't have horrible consequences if someone gets the user's password for it (in my opinion at least), there was no way I was going to store that password on disk unencrypted.  After all, users have a bad tendency to use the same password for multiple services, and one of those other services might contain important information.

So I dug into the Keychain documentation, and it took me a while to figure it out.  Meanwhile, I was learning Bindings for the Mac App, since in my time programming iOS, I'd never had the chance to use Bindings before.  And I decided that it was a good opportunity for me to combine the two and learn something, and maybe help someone else along the way. I fought with it off and on for a month or so, and released it under the MIT license at the end of July.

This is the result.  It's a project that simplifies using the Keychain by making it accessible through methods patterned after NSUserDefaults.

Their Data

So here's the problem, anything you persist in your App unencrypted can easily be extracted by a program like this,   If you put your own encryption in your App, you could run afoul of Apple's encryption policies and potentially Law Enforcement Organizations.  The KeyChain makes it possible to protect the data that you persist from (all but the most determined) prying eyes.

Now many programmers don't think they're persisting any data that they need to protect, because they don't get passwords from their users.  But think for a minute about other information the user might not want anyone to be able to see.  And then think about any data that you wouldn't want the user to be able to read (or alter).  I don't write games myself, but when I talk to my friends that do, I hear them complain a lot about people "cheating" by trying to hack their save games.  While you wouldn't want to stick a huge amount of data in the keychain, some strategically selected pieces of data (current amount of "gold" the user has, or maximum hit points) might be appropriate to store in a safer location than in a file on disk.

How to Use it

I intentionally wanted to write this library to be as easy to use as possible, so I decided to make it match the semantics of NSUserDefaults, since that's in every iOS programming book I've ever seen, so in theory, it should be well known to anyone needing it.

To install it, check it out from github, grab the 4 files in the PDKeychainBindingsController folder (the .h and .m files for PDKeychainBindings and  PDKeychainBindingsController) and drag them into your project in XCode.

Then, when you would normally have used:

[NSUserDefaults standardUserDefaults]

You should be able to call

[PDKeychainBindings sharedKeychainBindings]

instead (at least for the most common methods).  If you're doing an OS X App, and you're binding a NSTextField or the like, then where you would have called

[NSUserDefaultsController sharedUserDefaultsController]

use

[PDKeychainBindingsController sharedKeychainBindingsController]

instead (again, at least for the most common methods).

There are two differences, the first is that the Keychain API only wants to work with Strings (well, NSStrings).  So if you want to store something else in there, you need to convert it to a string yourself before you put it in the keychain (and change it back it when you take it out).

The second is that, in order to simplify it, I took out the need to run the synchronize method.  As soon as you call the set method, it gets persisted.

I'd like to thank Chris Adamson and Noel Llopis for unwittingly helping me decide on the topic for this post.

Reader Comments (2)

Hey Carl,

thanks for sharing your library - I agree anything but the keychain will sooner or later be cracked by the smart boys who don't have other ways to spend their time.

I looked at your code however and I believe you have an issue with memory management - remember ruleN1 - you need to have as many releases as retains? In your example iOS app you have 2 releases and 2 times setting to nil for 0 retains - basically you don't need all that code, because you're sending messages to nil objects after the first time anyway.

best, Marin

September 4, 2011 | Unregistered CommenterMarin Todorov

Hi, Marin,

You are correct. In -viewDidUnload in PDKeychainBindingsControlleriOSExampleViewController.m I am setting properties to nil more than once.

I was trying to learn accessorizer</A> (which is a really cool tool by the way) and I was playing with the different deallloc preferences, and apparently I changed them but didn't clean up after myself. Totally my bad. Thanks for catching that. I'll push a new version.

-Carl

September 5, 2011 | Registered CommenterCarl Brown

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>