I want to store sensitive data in an iPhone application but also have it be unlock-able via touch ID. I've thought of some options, none of which fully accomplish my goals and would like some advice on implementation.
Password protect app and encrypt data - Store only data encrypted with the user's password. Ask for password every time when decrypting to view data. I don't see how Touch ID would work in this scenario. It is secure but a pain to enter in password every time.
Password protect app only - Store raw data and only allow access if the user supplies the correct password / touch ID. This accomplishes the user experience I want but is that poor practice? Will Apple ultimately reject this method because the sensitive data is not encrypted? Keep in mind I am only storing data locally, there is no cloud/web server.
Scenario 1 with cache - The user enters in their password once a day, data is fetched, decrypted and then cached. The user need only authenticate the app while the decrypted data remains in cache. Clear cache if application is closed or a time limit is reached.
What does everyone think?
You have a few options.
Assume the user has their passcode enabled, and know that that means the DB is encrypted when the device is locked. For some cases, this is enough.
Encrypt the Core Data using Encrypted Core Data. FYI, this does work, but it has lots of limitations and bugs. We used it in an enterprise app and I regret using it.
Move away from Core Data to SQLite with SQLCipher. This is what I prefer now.
Bear in mind that you still have to deal with the DB key if you do per-app encryption. You can do this in a number of ways.
In many cases, you can just store the key in the Keychain and that's sufficient.
You can also require passcode/Touch ID/Face ID when launching your app/accessing the keychain item
Finally, you cal require the user to enter the passphrase
Regardless of your choice, use a key-derivation function such as PBKDF2 ~100,000 times to make brute forcing harder. Never store the actual DB key (which is derived).
Related
I'm making an app in which I need to save an array of type [Card], where card is the struct:
struct Card : {
var image : UIImage? = nil
var name : String = ""
var titles : [String] = []
var data : [String] = []
}
What is the best way to persist this array considering that it contains data such as credit card numbers?
Would it be enough to enable Data Protection under the Capabilities tab in XCode? At the moment I'm saving using Codable.
There is no right answer to this, but it's a great way to see how much a person has dug into iOS security. If you're interviewing with a bank I'd almost definitely expect someone to know something about it, but all companies need to take security seriously, so here's the ideal list of topics I'd expect to hear in an answer:
If the data is extremely sensitive then it should never be stored offline on the device because all devices are crackable.
The keychain is one option for storing data securely. However it's encryption is based on the pin code of the device. User's are not forced to set a pin, so in some situations the data may not even be encrypted. In addition the users pin code may be easily hacked.
A better solution is to use something like SQLCipher which is a fully encrypted SQLite database. The encryption key can be enforced by the application and separate from the user's pin code.
Other security best practices are:
Only communicate with remote servers over SSL/HTTPS.
If possible implement certificate pinning in the application to prevent man-in-the-middle attacks on public WiFi.
Clear sensitive data out of memory by overwriting it.
Ensure all validation of data being submitted is also run on the server side.
Sensitive data is not necessarily more secure in the cloud than on a device. Devices can be lost but most data breaches occur with data stored in the cloud. A large database of credit card numbers is a much more attractive target than a single persons credit card information stored on a device. Also, it is quite difficult to recover data from a properly secured iOS device (according to the FBI at least).
That said, any iOS app storing sensitive information should have it's own layer of security above that offered by the device including it's own user authentication process.
Disregarding the numerous reasons not to do this, a good way to securely store local data on iOS is trough the Keychain. It's encrypted with your passcode by the device, is preserved for your app even if it is un-installed, and syncs between devices. The API is kind of hard to understand for beginners, so a wrapper such as https://github.com/kishikawakatsumi/KeychainAccess is a good tool to get started.
In Order to save our apps sensitive data, we should use Security services provided by Apple.
Keychain Services API helps you solve these problems by giving your app a way to store the small amount of user data in an encrypted database called the keychain.
In the keychain, you are free to save passwords and other secrets that the user explicitly cares about, such as credit card information or even short sensitive notes.
You can refer this link for a detailed description of using Keychain Services API.
I am working on the app that require protection screen for the app.
This screen looks like :
I already done all features expect one. It is proper saving of the pin code.
I read about iOS Keychain and think it is quite suitable approach to save sensitive information.
But I would like to hear opinion from others is it enough? Or what should i use to protect this (pin code) information.
Now it is working like:
Set
Pin -> Keychain
Get
Keychain -> Pin
Also I consider hashing:
Set
Pin->Encode->Keychain
Get
Keychain->Decode->Pin
Saving a PIN is similar to saving a user password - one should never do this in plain text even when you store it protected like in the keychain.
At least save it as salted hash, better use a password hashing scheme (one-way security function designed for processing passwords and PINs) like PBKDF2, bcrypt, scrypt or Argon.
In most cases the keychain should be enough. But there is no 100 percentage solution. If an attacker has access to the hardware and software you can only make it harder to get the data, not impossible.
That means in your case an attacker already needs access to the device and the device pin code / touchid (if set) to install a jailbreak. Only then it's possible to get access to the content of the keychain and your stored data inside.
An additional encoding of your keychain data requires to store the key for the encode/decode somewhere. You have to save it somewhere else, e.g.in the user defaults, but the keychain already has the highest security level. Encoding makes sense for the real user data (the data you want to secure with the pin: access token, file encryption password, ...), because for these data it may be importend to destroy them in app deinstall/reinstall process. The user defaults will be removed when deinstall, the keychain not.
Scenario: User deletes app and sell his/her phone without resetting it in device settings. Buyer installs jailbreak -> old data in keychain should be garbage/unreadable.
Conclusion:
Think about it: What user data do you wanna secure with the pin? These data are also located inside of the keychain, even if it's only an access token for web requests or a password for an encryption. You don't need a higher security level for the pin than for your data ;)
In case of a pin your solution should be enough. But it's imported that your real user data should use the same security level or a higher one.
Update
There is a higher security level than the keychain: "Secure Enclave". It's mainly used for saving the touch id informations. Apple do not documented it, so I wouldn't recomend to use it yet.
There is a project called Tidas to make it accessible for the community.
I'd appreciate that someone could make it clear some questions I have regarding Data Protection feature:
Is needed/recommended to enable Data Protection to encrypt and protect the SQLite files managed by Core Data? If so, what should I do to encrypt and protect such files?
I followed a tutorial for using Keychain and it said that complete level of Data Protection had to be enabled for the App ID in the Apple Member Center, so that I did. However, it said nothing about also enabling Data Protection in the Xcode's project, so I didn't. It seems that I can access Keychain in my iOS app without problem, but this looks weird... should I also enable Data Protection in the target's settings?
Thanks so much
It depends what you're storing there and thus what is at risk if someone gains access to it. In most cases you don't need to encrypt the data in the DB specifically as someone will use a device lock to secure the device and any specific data that you want to make secure should be stored in the keychain. This is usually the user identifying data and account authentication tokens.
If someone gets access to a device that is unlocked (pin code / touch ID has been cleared or authenticated) then they can do pretty much whatever they want with the device (keychain and automatically encrypted data) and you can't stop them (at best you can slow them down).
Apple does mention you can limit access to Keychain data if someone tries to add their fingerprint after-the-fact. More info in the Keychain section of https://www.apple.com/business/docs/iOS_Security_Guide.pdf
The only thing you can do really is to explicitly encrypt the data which requires it using a key that is explicitly entered by the user each time you need to encrypt / decrypt. That key could be stored in memory temporarily, but you can never write it to disk. In this way the user has to enter the key to use the data and the key can only come from the user.
I an building my first iOS application and I need to store the user registration details of the user using the application. The details include his mobile number and a unique id( uuid ) which I use to contact with the backend. It would be great if I could get a suggestion on where to store this user details.
Should I be storing this in the NSUserDefaults or should I be using Keychains to store this data or even may be a using a user model in the database ( I would need a database in any case to store a few other details ). Just to add on, I also would like to perform a few validations like if the mobile number is of proper format and so on before I could actually save it. Also can any one please suggest on the security aspects of different storage mechanisms possible here?
Any help on this would be much appreciated.
The most secure way would be to use keychain services as the data is encrypted but in your scenario it seems a bit over kill. I would recommend either just using NSUserDefaults or an sqlite database I wouldn't really recommend storing in a plist as this can be accessed really easily.
But this all depends on the data you are getting, if it was just uuid and mobile number then NSUserDefaults would do probably, whereas if you were getting usernames and passwords and other personal data I would looking a mix of keychain and sqlite database.
Also you could use coredata file to store user data but seems a bit over kill as well for for such little data.
Just a little note you are actually not allowed to get the iPhones mobile phone number programmatically, getting this would use Private APIs that Apple would reject your app for using.
2.5 Apps that use non-public APIs will be rejected
So you would have to ask he user for this.
Database selection is totally depend on the architecture and security, if you just need to store the few information like login details and some field then Keychain for login details and plist for data is best option, but if your application also working with services and fetching and saving lots of data and continuously updating it then a serious database structure required. In that scenario core data and sqlite both are good option depends on your preference
Following ways you can save details.
In NSUserDefaults
In coredata file.
In sqlite database
Plist file.(Not recommended)
You can save data at server site using webservice.
Any one of these you can use according to your requirement and data.
Cheers :)
If you store information on the UserDefaults, a jailbroken device can see the information you have stored, it is a plist after all. If you are going to keep sensitive data on your device, user defaults itself is not a good option. Possible alternatives:
Use keychain: Keychain is a tool to keep usernames & passwords securely on a device; so you may need to find a way to convert all the info you have mentioned ( a dict, I presume? ) into NSData and put into/get from the keychain but it's been explained on other threads. Additionally, keep in mind that when the app is deleted, keychain data will persist on the device.
UserDefaults & encrpytion: If you can encrypt the data yourself, than using UserDefaults might be a better option. Its more straightforward than keychain and it will be deleted if you delete the app from the device (which may be the thing you want, or not. It depends)
I am making a app where I need to store some login details.
I searched over internet and found usage of NSUserDefaults has some security issue.
As for keychain, how much data can I store for a single app?
The other option using sqlite also has some security issue.
About application update, how can I preserve data in the next application update.
So which one should I go for?
NSUserDefaults is a big NO for storing any secure data.
If it is only pertaining to user's username & password,i.e sensitive information, then Keychain is the best thing to use.
For other kinds of data(not sensitive) you can use Core Data to store information.
When an update takes place, you can explicitly copy data that is present & import it to your update.
Keychain data as such remains available to the app, after an update.