granoff / Lockbox

Objective-C utility class for storing data securely in the key chain.
MIT License
847 stars 87 forks source link

SecItemCopy and SecItemAdd errors #45

Open RajivRamaiah opened 9 years ago

RajivRamaiah commented 9 years ago

Below is a sample code snippet from my program. I originally was trying to store an NSArray in keychain but when I retrieved it it would no longer be an array of GLAAccount *objects, but an array of strings, so I could not access the property on the objects in the array. Now I encode the object's properties into a string and then decode it after I pull it from the keychain using class methods for the object class, in this case GLAAccount. Occasionally, when I pass data to the view controller the below code is in, the saveAccess method is run and I get a secAddItem error and if I load the data from keychain I get a secCopyItemError. I have set the accessibility as kSecAttrAccessibleWhenUnlocked. Any thoughts?

//save data from self.accounts in keychain
- (void)saveAccess{
    //clean up the stringArray
    [self.stringArray removeAllObjects];

    //encode every account into a string and add it to string array
    for(GLAAccount *account in self.accounts){
        NSString *string = [GLAAccount encodeAccountObject:account];
        [self.stringArray addObject:string];
    }

    //save string array into keychain
    NSString *key = [NSString stringWithFormat:@"%@accounts", self.currentUser.username];
    [Lockbox setArray:self.stringArray forKey:key accessibility:kSecAttrAccessibleWhenUnlocked];
}
granoff commented 9 years ago

I doubt the accessibility setting has any bearing on the behavior you're seeing, but I could be wrong.

You note that you have to encode and decode your array elements. Have a look at issue #44 which has a lengthy discussion about the problems with saving nested complex objects like an array of non-standard objects. This isn't what is causing your issue, I bet, but I wanted to point it out.

Although not ideal, you might try removing the item first by setting the value to nil before setting a new value. For example:

[Lockbox setArray:nil forKey:key];
[Lockbox setArray:self.stringArray forKey:key];

In fact, just the setArray call will replace an existing value by deleting the old one then adding the new one, so this breaks up that operation a bit by explicitly removing the old value then adding the new value, which might alleviate the problem. Kind of a guess, but worth a try.