I would like to store some encryption keys which I use for data transfer in the keychain to keep em safe.
My issue is, how do I keep em safe until I get them into the keychain? If I hard code em into the app, and add them to the keychain on launch the first time, then a hacker would be able to retrieve them by decompiling, any input is highly appreciated.
I would like to add that my validation of the data transfers are also dependent on a user password, which is safely stored in the keychain, but would still like to keep my encryption keys safe.
Thanks.
In 3 words: SSL web service
Related
I am saving an important key in the iOS keychain. Everything seems to be working okay right now. There has only been only one issue. The keychain data is still alive after you delete the App. Which I was able to resolve by checking if the App has just been installed and deleting the data in the keychain. However, I want to be sure if there isn't any more issues or pitfalls I should be looking for.
The Apple keychain uses 256 bit AES encryption to secure data. It is ostensibly the mechanism that Apple uses internally to store private data such as your passwords as well. Other than your comment about the data being persisted after you delete your app (which is a feature not a bug), there’s not going to a “gotcha” when using the keychain API. Just realize that the keychain is just a fancy encrypted database, and follow best practices for what you should store, and when you access / write to it, like any other DB.
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.
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 am developing a corporate app that will be publish on an internal store.
The app is just supposed to keep in memory some credentials but I can't store them on the device for security reasons.
I want the app to stay in background as long as possible but I don't know what is the best solution knowing that I won't have to publish the app in the AppStore.
I read about the option in plist Required background modes, but I don't know which option is the most efficient for my situation.
Firstly, you don't need to keep running app in background, second you can store "those [secret] credentials" in keychain store with some encrypted format, SHA1 or MD5 or any other cryptographic hash functions can be use for this, third the benefit of this is you can access to them from your different apps as well (by using the same encryption key to decryption and accessing keychain store item), at last when you no longer need it, you can even delete it. The only thing you need to keep secret is keychain store key (which you used to store credentials) and also your encryption key (to used with cryptographic hash function).
There's are several libraries available to easily manipulate data in keychain store, here's the one, and here's the solution to apply MD5 or SHA1.
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)