jrendel / SwiftKeychainWrapper

A simple wrapper for the iOS Keychain to allow you to use it in a similar fashion to User Defaults. Written in Swift.
MIT License
1.59k stars 340 forks source link

Use String for SecAttrAccount key, not data #80

Open petrdvorak opened 7 years ago

petrdvorak commented 7 years ago

Currently, the KeychainWrapper.swift uses Data type as a "key" to store records. We got our head scratching for quite some time and we could not find any actual benefit of the current code.

// Uniquely identify the account who will be accessing the keychain
let encodedIdentifier: Data? = key.data(using: String.Encoding.utf8)

// ...

keychainQueryDictionary[SecAttrAccount] = encodedIdentifier

link to code

Why don't you simply use String, like Apple does?

You use String everywhere up until that point, then you convert it to Data just before storing the record...

jrendel commented 7 years ago

So I don't really have a good answer for you as to the why. Years ago I pulled this code from a Ray Wenderlich tutorial in Objective C (https://www.raywenderlich.com/6475/basic-security-in-ios-5-tutorial-part-1). At the time I didn't have full understanding of the keychain api myself and used the class through several apps, making small changes to it over time, always thinking it would make a good open source library to put out there for other to use. When Swift came out, it was one of the first things I wrote in Swift during the beta as a way to work on learning the language.

So it has evolved over time from that original tutorial, where those values had been encoded and its just not something I've ever considered fully since then.

Do you see a downside to encoding it? The issue with changing it now, is the major migration issues everyone using the wrapper would face for existing keys.

petrdvorak commented 7 years ago

@jrendel Thank you for the explanation. We will have to figure this one out on our end. Fix of this issue will not help us just for the reason you mentioned, anyway. We already have ~100k users with records with Data keys (Touch ID protected... bummer...) that we need to somehow migrate.

Couple notes:

jrendel commented 7 years ago

Thanks for the background info on this. I agree, it should be changed to use a String. I'll have to think through the best way to do so, but I do like your idea of a legacy story flag. That would be a simple way to address it. I could also do that in conjunction with a fall back, if it attempts to read a key just using a string and can't find it, to try with the encoded key (for users of the wrapper who don't notice the new configuration flag).

sacriaf commented 4 years ago

I've ran into a bug due to this issue recently when using this library in a MacOS app (I understand that's not officially supported yet). While the current implementations happens to work on iOS apps (I've verified that the Account value for general password items are set correctly in the keychain sql db), it doesn't work on a MacOS app. On a MacOS app, the general password keychain item gets created without an account value (verifiable via keychain access). Simply changing the value type from data to Strings fixes the issue. I realize it's been a while since this thread was created. Has there been any new insights on a patch? Regarding migration, my limited testing on iOS seems to indicate compatibility with keychains created before the change.