Losing access to the keys stored on iOS Key Chain - ios

We have an app on the iPhone App Store which needs to store the user id and password on the device for features like Touch ID and Remember Me.
Both user id and password are encrypted and the respective AES key is stored in the device key chain.
Now, the problem statement is : we are unable to retrieve the AES key from key chain every time we update the app from AppStore and also when user updates iOS on their device (eg : from iOS 9.1 to 9.2).
Since we are unable to retrieve the key, we are unable to decrypt the user id and password that results in failing a couple of key features every time user updates the app (eg : Remember Me and Touch ID).
This is becoming a huge concern since the issue continues until user totally uninstalls and reinstalls the app.. When user reinstalls the app, every thing works fine. We can enable Remember Me, Touch ID features and they are enabled fine and works fine.
What must be going wrong ?

In general keys in the keychain persist across update and even deletion and re-installs. So, there is something you are doing that is not correct. Please provide more information.
It is not necessary to encrypt the name and password, they can be stored directly in the keychain, the keychain encrypts it's contents.
Are you changing the Bundle ID when you update? If so have you made the keychain available to a group all the updates belong to?

Related

Unique id for identifying devices even after clearing app data [duplicate]

This question already has an answer here:
Getting two different device IDs from same iphone
(1 answer)
Closed 5 years ago.
The backend apis I am using take unique device identifier and generate responses. In the client side, I am generating UUID for this unique identifier since Apple does not allow getting IMEI. I am storing the UUID (UserDefaults storage) and fetching it every time an api call is to be made. Now, my problem is that if the user clears the app data, the stored UUID gets cleared and a new id has to be generated. However, with this new id, the user request becomes invalid. How can this issue be resolved? Is there some kind of id that remains constant for a single device (something like device id in android)?
you can use the keychain secure storage to store the UUID, This will keep persisted even if you uninstall and then install the app.
Here is the 3rd party library written in Swift which simplifies the use of keychain.
https://github.com/evgenyneu/keychain-swift
By #Anand (Pls see the first comment).
Keychain is the actually good choice for storing UUID of the app in a secure manner, that can be persisted even when the app is deleted and re-installed. But in case, if the user resets the device for clearing the app data, even the keychain data will be deleted.

Where to store whether Touch ID is enabled on iOS?

Assume a user enables Touch ID in my app. I need to save this state somewhere. I have two options: NSUserDefaults, and the Keychain.
NSUserDefaults: The problem with storing a boolean fingerprintEnabled in NSUserDefaults is that this flag can be modified. So, an attacker with physical access to the device can simply edit this flag and bypass fingerprint authentication in my app, and gain access to user's secure offline data.
Keychain: This is great, as it is encrypted and cannot be modified externally. However, keychain values are persisted across app installs/uninstalls. If a user uninstalls the app, perhaps because Touch ID isn't working properly, and re-installs it, it will still prompt for Touch ID, even though the new app installation should reset all state.
So where's the best place to store state on whether fingerprint authentication is required?
If you are so concerned about the security of data saved in NSUserDefaults why don't u use the combination of both NSUserDefaults and Keychain
Save a variable in NSUserDefaults lets say installed. This you'll set it to true in AppDelegates didFinishLaunchWithOptions. This you can use as a reference when should you reset the value of fingerprintEnabled in keychain.
Problem with saving it in key chain is you don't know when to reset it. The value in NSUserDefaults now will help you decide when to reset this value.
Because the value in NSUserDefaults will be removed on uninstalling the app, when u uninstall and reinstall the value of installed will be absent in NSUserDefaults now you can go ahead and reset the value of fingerprintEnabled in Keychain if present (Obviously this should be done in didFinishLaunchWithOptions before you set the installed).
On subsequent launches value of installed will prevent you from resetting the value of fingerprintEnabled.
I know this is not the most efficient approach as it uses both NSUserDefaults and KeyChain but solves the problem though.
If using NSUserDefaults is unsafe, using the keychain is unsafe too, so I would use the NSUserDefaults, because it is easier to implement. Let me explain: If the user can just edit the user defaults and get access to the data, this means that the data is unencrypted. (Or at least, it's encrypted in a way that is easy to break if you have access to the source code of the app.) If the data is unencrypted and you use the keychain to store the boolean, the user can as well just patch the binary to omit the keychain-check. Or he may just find the unencrypted payload in the application binary and inspect it.
But now for something more constructive... :) The best way to implement Touch ID protection, is to use Touch ID to unlock a secret key, and encrypting the payload data with that secret key. If Touch ID is disabled, you just use a hardcoded key instead (and use some kind of basic runtime obfuscation, like base64_decode to make it not too easy for attackers.) You can store a boolean in the user defaults (e.g. "data_encryption_enabled")*. If it is YES, you ask the system for the secret key for the "data_access" item. You then decrypt the data with that key (I suggest to use AES128). If "data_encryption_enabled" is NO, you use "9fajw9e8" as the secret key instead. It's easy to see, that if an attacker manages to change "data_encryption_enabled" to NO, this will not unlock the data.
A few more things to consider:
When the payload is saved in a way that it can be backed up to iCloud, you should test if restoring the app from the backup to a different device makes the data unusable. If the data is stored only locally (e.g. either in "Caches", or in "Documents" with NSURLIsExcludedFromBackupKey set to YES/true) this is not an issue.
The algorithm that generates the secret key should be secure. (E.g. use SecRandomCopyBytes)
*) all strings in this example are made up by me, you can choose them however you like.

Store data securely in the device till app is present in iOS

I want to store one key value pair very securely in the device. But, I want to persist the data till app in present in the device.
Once app is deleted this data also should get removed.
NSUserdefault is not very secure.
Keychain is another option as it is secure but it persist data even after app will get deleted from the device.
How should I proceed.
Any help?
Create a random encryption key. Store the encryption key in keychain. Encrypt the data with the encryption key. Store the encrypted data wherever is convenient within the app's directories. If you want to preserve it across restores, then store it somewhere that is backed up (such as Library/Application Support or in NSUserDefaults). If you don't want it preserved across restores, store it in Library/Caches (you may need to do some research on that; "the system may delete the Caches directory on rare occasions when the system is very low on disk space" so there is a danger of losing the data, but you had to deal with that in case of restore anyway). You also can use NSURLIsExcludedFromBackupKey to avoid backing it up.
When the app is deleted, the encrypted data will be deleted. You will leave the random key in the keychain, but this is just a random number of no value.
I have used one flag which is stored in keyachain that will set to true whenever app will get launched for the first time.
When my app will get launched for the first time this flag will not present. I will store this flag in keychain with value true and I will store my secure information in the keychain.
If my application is launched for the very first time and flag is present then I will delete the flag and data first and then proceed with step 1.
In this way, I have solved my problem of app is using the already stored data in keychain even after installing and launching for the first time. If user will delete the app, keychain will contain my secure data but that will be of no use as it is encrypted with random key.

How to uniquely identify users ios7+?

I want to know who the user is without them actually logging in. There are bunch of methods on the internet and the one I am currently using is:
static let DeviceId = UIDevice.currentDevice().identifierForVendor.UUIDString
The problem is this resets when the user deletes and reinstalls my app. Also somehow this value changes in about 1-5% of the users without them actually deleting the app. It happens after they upgraded to a new iOS version. Possibly happens when they change appstore country too.
I want the user id to be unique no matter whatever the user does. Kind of like how Whisper app works.
What is the best way to do this? Advertising identifier looks really good on paper, but does apple allow using that just for user login info?
Should I use keychain? icloud? Is there some other value I can use?
Here are some sources I read about this topc:
http://tinymission.com/post/ios-identifierforvendor-frequently-changing
http://possiblemobile.com/2013/04/unique-identifiers/
How to preserve identifierForVendor in ios after uninstalling ios app on device?

Where is Password for iOS Keychain unlock stored

As we know OS X needs master password to unlock keychain and decrypt all data that is stored there. In general master password is stored in user's brains so there no any direct IT ways to compromise this password.
At the same time iOS makes some simplifications and it doesn't require master password that known only by user. So I became interested how is logic for iOS keychain unlocking and data decrypting implemented and found such explanation in Apple docs:
In iOS, an application always has access to its own keychain items and
does not have access to any other application’s items. The system
generates its own password for the keychain, and stores the key on the
device in such a way that it is not accessible to any application.
As I understand iOS generates master password by itself and stores it in some specific place.
My question is: does anybody know or have any ideas what is it place or way that used for storing master password that guarantees preventing from any IT attacks or third party accesses?
(I found some similar questions like this, but there are no any specific information.)
You can find a lot of information in the Apple iOS Security Whitepaper
Essentially the passcode is "tangled" with a device specific ID that is not available to executing code in order to generate keys. The keys used to unlock files and the keychain are kept in memory while the phone is unlocked (or after first unlock for some protection classes) but are discarded on lock or reboot (again depending on the protection classes) but the passcode itself is never stored in memory or a code accessible file system.

Resources