Learn about the various concepts in how keychain data access happens. Understanding how data is fetched is key to getting the right data and hopefully efficiency.
- [Instructor] The next thing we want to look at is how to retrieve items out of the keychain. In some ways it's similar to adding items to the keychain, particularly in using this query dictionary. We're going to specify what we want it to match. We're going to use a function called SecItemCopyMatching and in the query dictionary, we'll specify what we want it to match on. So let's look at the documentation for that function. Here we have the SecItemCopyMatching function and there's two parameters, query and result, kind of like we saw when we were adding an item. For the query, there's a little bit more to it. We specify the item's class just like we did before, in our case, the generic password, and also any attributes we want to match. In our case, it would be the account for the username but you can specify other ones for things like label and type. There's also search parameters that you can specify and if you click on Search Attribute Keys and Values, you can see the various attributes you can specify for that including MatchItemList, Matching Issuers, that would be for certificates as well as some others and all the way down here at the bottom, you have a MatchLimmit which defaults to one. So that's what we'll use for our password. Then you also specify one or more return types and this is where it gets a little bit tricky. You can specify one or more return types. So it's still going to return one thing so that's where it gets a little confusing. And then the result itself. This last parameter. You pass in as a CFTypeRef which if we look at that, it's just a type alias to an AnyObject. Whatever gets returned is going to be set in this parameter you pass in and it passes back an OSStatus like the add did. So let's look at these return types. So I'm going to click on Item Return Result Keys. Now there's four of 'em. I'm going to skip the first two and go down here to the third one first. In this case, we could specify in our dictionary the SecReturnData and specify the value as true. It will return a CFData representing our data in the keychain database and it specifies here it's typically what you want for password items. You're probably looking for the password, you specify just return me the data, it sends you back the data and you convert it back to a string. You have your password. You can also specify the SecReturnAtrributes. This will return a dictionary that includes all of the attributes that you specified for that item and maybe some empty ones. Things like the create date and modify date will be populated in there as well. But if you want both, you can specify both. Notice it says here you can use the SecReturnAttributes or more than one return type. If you specify both the return attributes and the return data, you still get a dictionary like the ReturnAttributes case but now the data is an item in that dictionary so you can still get to the data just fine. Notice that when you specify a match limit greater than one, you get returned an array. So kind of like when you parse JSON, you kind of need to know a little bit about what you're getting back, an array or a dictionary. That's kind of how it is here. You can check for it in the code or you may already know what you're going to get back. Now, for things like certificates and keys, you might want to get a reference to the item. It depends on what you're storing but if you set in the dictionary the SecReturnRef as true, you'll get back this reference and then, especially if you match on more than one, you can call the SecItemCopyMatching with the key of SecMatchItemList and pass in an array of those references. Similarly, you can use the SecReturnPersistentRef in the dictionary and set its value to true. And it'll return a persistence reference as a CFData and with that, you can store it, you can pass it around and it's persistent and again, you can use the SecMatchItemList to get those instances from the keychain when necessary. For us, we're dealing with these password items, so we can use the data or the attributes or both and get back what we need from the keychain, in our case, the password. Now, I know this is a little confusing but I wanted to go over it conceptually first and then we're going to exercise the code using this. So again, going back to the CopyMatching function, we're going to specify our query with our class, the generic password, the attributes, in our case, at least the account, the username, we could specify parameters if we wanted to match on more things or a limit but they don't want you to use this limit on passwords because in some cases, you might match on more than one password and it require more authorization. And then also we specify one or more return types, in particular the attributes and the data and once we get that back, we'll have our password.
- Creating keychain queries
- Storing generic passwords
- Retrieving data from the keychain
- Handling search results
- Updating and deleting keychain values
- Working with keychain access groups