One of the most interesting things I’ve been working on lately is security in iOS applications: certificate pinning, encryption and gaining a finder understanding of Keychain. It’s amazing how vulnerable our applications can be if we don’t have a working understanding of modern security concepts when building out apps, especially for users of our apps.

Keychain Wrappers are Everywhere

So if you’ve ever wanted to store secure data in the device’s Keychain, you’ve probably used a wrapper. Even Apple offer their own wrapper to work with it as it’s an older C API which isn’t exactly easy to work with. Here’s the problem; when I was working with a Keychain pod recently it started to bother me that I didn’t know a huge amount about it, it was vague and searchable-when-needed, but where’s the mastery in that?

So I started to work on a little wrapper of my own for basic password storage in an app’s keychain and I thought I would try and explain what’s going on without making your life miserable hunting down all of the Konstants everwhere (‘k ‘in iOS is the first letter for the Hungarian word constant).

When you want to insert into or query the keychain, you need to work with a dictionary and that dictionary requires certain keys and values to work properly. Let’s say you wanted a method that prepared a dictionary to insert a user-set password into the Keychain. It may look something like this:


1
2
3
4
5
6
7
func generateKeychainQueryDictionary(with keyChainPassword: String) -> NSMutableDictionary {
        let result = NSMutableDictionary()
        result.setValue(kSecClassGenericPassword, forKey: kSecClass as String)
        result.setValue(keyChainPassword, forKey: kSecAttrService as String)
        result.setValue(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, forKey: kSecAttrAccessible as String)
        return result
    }

Huh?

So, before you run away fast, let me break this down a bit. We’re passing in a string and returning a formatted dictionary that we’ll use later. We’re still working with older APIs so we need an NSMutableDictionary as opposed to a more modern Dictionary class in Swift.
We’re setting the class type for this dictionary, the class the keychain knows it’s working with which is kSecClassGenericPassword – just think of this as secure generic password. We cast this as a string for the key in the dictionary.

Next is crucially important: the unique value of the keychain item. What if you have two passwords that are the same in Keychain? I know I do! So how does it decipher which is which when it is a password class (as opposed to a certificate class or whatever)? It uses a combination of this and other attributes, but just know kSecAttrService is a unique identifier used for retrieval later.

Finally kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly means that the keychain item we’re storing can be accessed later when the phone is unlocked and the app is on screen. You could change this and make it accessible all the time, when the app is running in the background etc.

What Next?

So you can see that the dictionary that we pass to the keychain methods we’re use later are quite specific and ultimately clear once you get the hang of working with them. It’s sensitive user data so it’s very important to get it right.

Next let’s look at the method we’ll use to fetch the stored password:


1
2
3
4
5
6
7
8
9
10
11
12
13
func fetchKeyChainPasswordFromKeychain(with passwordQuery: String) -> String? {
        let keyChainQuery = generateKeychainQueryDictionary(with: passwordQuery)
        keyChainQuery.setValue(kCFBooleanTrue, forKey: kSecReturnData as String)
        keyChainQuery.setValue(kCFBooleanTrue, forKey: kSecReturnAttributes as String)
       
        var fetchResults: CFTypeRef?
        let queryType = SecItemCopyMatching(keyChainQuery, &fetchResults)
       
        guard let fetchResult = fetchResults,
              let data = fetchResults?.value(forKey: kSecValueData as String) as? Data
            else { return nil }
        return String(data: data, encoding: .utf8)
    }

To break this down a bit: first we pass in a password to check for and use our existing method to generate our dictionary. Next we add a few properties: we are looking for return data and return attributes from the query so we set these as true, however the real magic happens when we use the SecItemCopyMatching method.

This method performs a fetch for items matching our query and takes a reference type which you pass in with an ‘&’. Our results variable is mutated and the results are stored in it. We then cast it as data and return that data as a string which should be our password!

You can see there are a few key players in working with Keychain – it’s quite low level but it just seemed to interesting to resist learning about and trying to explain in a way that might be a bit easier than sniffing around Google trying to understand what’s going on.

This article was heavily influenced by the amazing Agostini.