I would like to add simple password protection in an iPhone App that I am working on. I will probably use crypt() to store the password in my database which in in CoreData / sqlite format.
I think I have a pretty good understanding of how to create and store the password, but in case the user forgets their password, I would like to add a password recovery ability
This is the part that I'm struggling with in iOS. I want everything to be local, so I can't think of a way to use a link to reset a password.
I had thought about emailing the password, but in iOS there is no way to send emails without the person holding the device seeing the contents of the email.
The only way that I can think of is to have one or two "backup passwords" which is basically the answer to a question of the user's choice (or maybe even just storing a reminder question along with the password).
Neither of these are really that secure, although the data being protected in my app is not that critical, so I'm not looking for the most robust solution (just a decent solution that is not too hard to implement, not too inconvenient for the user, and not too hard for a hacker to break).
Suggestions are greatly appreciated.
Thanks,
Ron
Instead of recovering a password, you can prompt to reset a password using criteria that is set up when they initially create their account -- such as mothers maiden name, last-4, etc. This way, you don't need to worry about decrypting a password or sending it to the user. Once they answer enough security questions correctly, they are prompted to reset their password. You can store this data encrypted locally. You'll never need to send a password to the user.
The easiest way is probably to make "password protection" optional and display a warning ("if you forget your password, your data may be irrecoverable!").
It's not going to be that secure: The data is probably going to appear unencrypted in a phone backup, unless you encrypt it yourself. The upshot is that determined users can ask you for help, and you can write them a tool that digs through the unencrypted backup and resets the password.
Avoid the built-in crypt(), which is probably DES-based and limited to 8 ASCII characters. Storing the plaintext password in the keychain is not too terrible an option.
Related
I have some data I’ve spent months collecting, cleaning and structuring. The app I'm building will be able to search the data. So far I'm storing the sqlite file in the users filesystem and not on a remote server because I want the search result to be instant to give users the best experience possible, independently of their connection speed.
But I've just discovered anybody with a jailbroken phone can just "steal" the information store in my sqlite file.
The last thing I want is for someone to get the result of my hard work and publish it on a website which could potentially makes the app useless.
Is there any way to stop this from happening?
Thanks for your help!
What you want is a form of DRM. Ultimately, DRM cannot prevent a dedicated attacker from getting at the underlying data. Anything the user can access can, in theory, be accessed by a malicious application.
You can encrypt the rows of the database and hide the key somewhere in the app, but an intrepid hacker will find it. You can download the whole file on first run and encrypt it with a key unique to that device, but then you have to store the key somewhere or have an algorithm for regenerating it--and a hacker can get at either (even if it's in the keychain.) If you require a network connection and use a key generated from something server-side and client-side... well, an attacker can just spoof the request and get that server-side component anyway.
So it really depends how secure you want to be. If you just want to keep honest people honest, simple encryption is often good enough. If you want to make a bulletproof DRM system... you'd be the first to accomplish it.
You can use Encrypted Core Data to secure your data.
This library actually decrypts your database at runtime. You can leave your PASSCODE in your .m file. (My assumption is that it is difficult to get the hardcoded PASSCODE from the object file)
And as #jonathan put it, if some person is desperate to get your data, they will.
EDIT:
As Zaph mentioned in the comments section, do not try to put password in your code either directly, or by obfuscating them in your code by some logic, as any one who is desperate to get your key could reverse engineer your binary and get it.
Is it possible to reverse-engineer my iPhone application?
Is there a way to password protect the SQL Lite db core data uses for it's persistent store? I want to make the DB available via iTunes but I want to be password protected so only I can open it.
CoreData doesnt have any built in password protection so you are going to have to roll your own encryption or obfuscation mechanism.
Alternatives could be obscure mechanisms (press the invisible button three times?) to send the file by email for returning the data-store to you rather than exposing the Documents folder in iTunes.
I guess the question is there a genuine need for password protection (i.e personal/medical records) or is this just the usual Corporate paranoia. If its the latter I wouldn't put too much effort in. IMHO.
Yesterday I posted this question about protecting files: Protecting the app sandbox
As mentioned, it appears that this is effective for protecting a file if the user has a passcode on the iPad. Naturally this raises the question of how to handle the encryption if the user does not. Now I have an idea, but am not sure if it's feasible or not.
Is there any way to override the encryption key to use a custom one? My gut instinct is no, but I figured there may be a way. (Btw, this is just an experiment for fun, I don't plan on submitting this to the app store...) My application has a login, and it would be very handy if this could be handled at the application level to accommodate users that do not have a lock.
However, I suppose it wouldn't be unreasonable to disable the saving feature if there is no device passcode... Any thoughts?
You can generate encryption key, based on login/password, this allowing user to open his files only if he know password. However, you'll need provide ability to restore data in some way if user will forget his password.
I like to use CoreData and their entity model into my projects.
I need to know that how to store sqllite database into Iphone securely.
As everybody knows when the Iphone broken with jailbreak it have file system navigatable, that mean for me, someone or somebody easly open or copy to another envorinment my sqllite db. How do i protect my db for these issues ?
Thank you
Answer in bold.
If they have jailbroken your iphone and have the will to steal data, they will probably have the ability to decrypt anything you put there; this is especially so if the data is of any value. To use encryption in this scenario your application will have to store the password somehow, unless you expect the user to enter this every time using the iphone keyboard -- which is a big no-no from a usability point of view. I suggest you rely on the access baricades and remote-wipe facility provided by apple.
If your a going to rely on apples 4-numeric pin as a password -- i.e., to balance useability.... well that only has 10,000 combinations.... not very secure.
However.... the simplest and the time-tested approach is to use a reversible encryption block-cypher in block-chained mode to encrypt the content of the sensitive columns, and to retrieve the password from the user every time the application is started.
-- edit : further discussion --
If I was expecting contents to be encrypted in a mobile way, I would expect the user of the contents to have a USB stick with the contents on it and a security hardened laptop/netbook with the something like truecrypt running on it.
I was not aware that a phone can be jail broken without the consent of the user ?
On the iPhone 3GS all data stored on the phone is encrypted.
I don't know what you are storing, but leaving the security to Apple may be OK.
Did you read this?
http://images.apple.com/iphone/business/docs/iPhone_Security_Overview.pdf
If you really only have under 10,000 records, and they are smallish - like say a short string or two in size, then you could just use an NSDictionary / NSArray with 10,000 items in memory at a cost of 10k*.256k = 2.5 MB in memory, which is not much. If the queries will be simple, then you don't need sql at all. Just run through all records on each search.
You could store an NSDictionary as an exncrypted file, password protected, with the user entering the password on each launch.
Are you worried about someone who has stolen the phone getting the information? Or the person who owns the phone getting to the files your app contains?
If it's not the user there are safeguards you can take, like the password presentation every time (hint: users will hate it and your app will get all 1-star reviews).
If it's the user you are worried about, you are insane to think you can protect anything the user has on their own device. You can just apply some simple obsfucation and call it good.
Here is what I got for a webapp login scheme.
Present in database would be two salts and hmac(hmac(password, salt1), salt2).
When the user go on the login page, he gets salt1.
If he has javascript activated, instead of sending the plaintext password, it would send hmac(password, salt1).
If he does not have javascript, the plaintext password is sent.
So, on the serverside, when getting a login request, we'd first check what is sent (passwordSent) against hmac(passwordSent, salt2). If it does not work, we'd try hmac(hmac(passwordSent, salt1), salt2).
Someone getting access to the database should not be able to login with the password hashes and I don't think (but I may be wrong) that multiples hmacs diminish the hash resistance.
Do any good crypto expert see any obvious error I may have done ?
This looks a little like security through obscurity, what is the point of using javascript to hash the password on the client side if you still accept plain text password from the client?
You didn't mention if this was over https, if you aren't using https then you may as well have no passwords at all. If you aren't running https then any MITM can see the salt you are sending as well as the javascript used to hash the original password so you have nothing gained.
As for your concern about the possibility of hmac collisions between two salts, that is probably very unlikely (depending on your hash algorithm) and how secure you keep your salt values. Even with MD5 that has had some collision attacks discovered and has a set of rainbow tables, you will be ok if you keep your salt very very safe.
Please, everybody, please stop trying
to implement custom crypto systems
unless you have a background in
cryptography. You will screw it up.
--Aaronaught
Well said!
Sounds pretty far-fetched to me. If the objective of this is to prevent a "man-in-the-middle" attack by virtue of the plaintext password being sent over HTTP, then use SSL.
Hashing on the client side accomplishes nothing; unless the salt is actually a nonce/OTP, and not stored in the database, then a man in the middle can simply look at the hash sent by the original client and pass that along to the server. The server won't know the difference.
If this is supposed to make it harder to crack if someone gets hold of the database, it won't. If the hashing function is cheap, like MD5, this won't be any more difficult to crack than one salt and one hash (in fact it's actually weaker, since hashing is a lossy function). And if you use a strong hashing function like bcrypt, it's already good enough.
Please, everybody, please stop trying to implement custom crypto systems unless you have a background in cryptography. You will screw it up.
Probably obvious to you already, but you're effectively letting people log in with two different passwords in that setup.
If you want to give people the option of sending their passwords with encryption, I wouldn't tie that to anything strictly client-side, and just force HTTPS, as Harley already implied.
You might want to look at HTTP Digest authentication. That is a standardized protocol which avoid clear text password in any case.