In my app there is a place where the user can enter in some sensitive information. I'm using a NSSecureTextField for that.
However, NSSecureTextField just uses a plain String to store its contents. This poses an issue because I would like to destroy that String instance, but that is impossible because strings are immutable.
When the user finishes typing his password, there would probably be 10+ instances of that password in memory.
Is there any way to somehow have a more secure method of entering text?
Related
I have created a suite of two different Flutter apps that share a single firestore database.
The first app generates a QR code that would then be scanned and verified by a user of the second app. The QR code information is a string that contains some information I don't want users to see by simply scanning the QR code with their camera app.
I want to encrypt the string in the first app before encoding it into a QR code, and decrypt the string in the second app after the QR code has been scanned, but that means I would need to have the encryption key accessible in both apps.
Would I have to hardcode this key into the apps or transmit the key through the database? How can I achieve this in the most secure way possible?
You can use almost any mechanism you want to transmit the keys, but the one thing you shouldn't do is transmit it through the same database as where you store the encrypted data - as that would put that data at risk if the database is compromised.
So mail them, text them, write them on a piece of paper and mail it, or you can organize an in-person meeting/party where you exchange them (h/t to Little Brother). It doesn't really matter how, as long as it's a different mechanism than you used to store/exchange the actual data that is encrypted with those keys.
You can hard-code them in the apps too, but what the keeps anyone from downloading that app too and using it? Or is that precisely what you want, in which case đź‘Ť
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.
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.
I have a fairly long HTML form that the user fills out. After filling it out, the user is given a preview of the data they are submitting. From there they are able to commit the data into the system or go back and edit it. I'm wondering what the best approach to handling this preview step is. Some ideas I had are:
Store the form data in a cookie for
the preview
Store the form data in a
session
Put the data in the DB, with
a status column indicating it's a
preview
What do you usually do when creating a preview like this? Are there other issues to consider?
Put the data as hidden fields ().
Why not cookie or session?
- If the user decide to discard this data, he may just navigate to other page. When he return later and see the data intact, he maybe surprised.
Why not database?
- If the user just close the browser, who clean up the data in your db? ... I would rather not write a cron job for this.
I'm not sure if it's the best-practise, but when I did this task, I've put it in a session. I expected the user to preview and submit/reedit the data during just single session so the session was enough for me.
If you want you preview to persist on your users machine you should use a cookie - that means the user doesn't have to sumbit/reedit the preview during single session, but can close the browser between this operations, and than return back to the preview in next session. Using this aproach, you have to consider that user can deny cookies in his browser. That's why people usually combine sessions with cookies together.
Putting the data in a database (with a status column) is not necessary unless you want to track and store the previews and edit operations somehow. You can imagine the database as a drawer in your table - you put there papers with whatever you want to store and find later. If you're just drawing a preview draft, and after the result is submitted, only a final version is stored in a drawer/database and the preview is crumpled and thrown away, than you won't put this in database. But if for some reason you think you will later go through the drafts, then they have to be stored in a database.
I'm not sure if it's clear with my english, but I did my best :D
I'd gauge it based on how difficult the form was to fill out in the first place. If it's a lengthy process (like information for a mortgage or something) and you have user logins, you may want to provide them an opportunity to save the uncompleted form and come back to it later.
A session is only good for (depending on your setup) tasks that will take less than an hour. Manual input of data (like CD/DVD cataloging) that is easy to start and easy to finish will be perfect to store a session. Likewise, if the person has to stop and root around for some documents (again, in the case of a mortgage app, or an online tax form, etc.), you'll have a really irate person if the session times out and they have to retype information.
I'd avoid directly injecting content into a cookie, since the data is passed for subsequent requests and, assumedly, you already have access to basic session functionality.
If you go with a DB, you will need to timestamp the access (assuming you don't just leave it around with some saved name as determined by your user, like 'My 2008 Mortgage Documents') so you can clean it up later. If the user does save it mid-form, just leave it around until they complete the form or delete it.
Let's say I need to access a web service from an iPhone app. This web service requires clients to digitally sign HTTP requests in order to prove that the app "knows" a shared secret; a client key. The request signature is stored in a HTTP header and the request is simply sent over HTTP (not HTTPS).
This key must stay secret at all times yet needs to be used by the iPhone app.
So, how would you securely store this key given that you've always been told to never store anything sensitive on the client side?
The average user (99% of users) will happily just use the application. There will be somebody (an enemy?) who wants that secret client key so as to do the service or client key owner harm by way of impersonation. Such a person might jailbreak their phone, get access to the binary, run 'strings' or a hex editor and poke around. Thus, just storing the key in the source code is a terrible idea.
Another idea is storing the key in code not a string literal but in a NSMutableArray that's created from byte literals.
One can use the Keychain but since an iPhone app never has to supply a password to store things in the Keychain, I'm wary that someone with access to the app's sandbox can and will be able to simply look at or trivially decode items therein.
EDIT - so I read this about the Keychain: "In iPhone OS, 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."
So perhaps this is the best place to store the key.... If so, how do I ship with the key pre-entered into the app's keychain? Is that possible? Else, how could you add the key on first launch without the key being in the source code? Hmm..
EDIT - Filed bug report # 6584858 at http://bugreport.apple.com
Thanks.
The goal is, ultimately, restrict access of the web service to authorized users, right? Very easy if you control the web service (if you don't -- wrap it in a web service which you do control).
1) Create a public/private key pair. The private key goes on the web service server, which is put in a dungeon and guarded by a dragon. The public key goes on the phone. If someone is able to read the public key, this is not a problem.
2) Have each copy of the application generate a unique identifier. How you do this is up to you. For example, you could build it into the executable on download (is this possible for iPhone apps)? You could use the phone's GUID, assuming they have a way of calculating one. You could also redo this per session if you really wanted.
3) Use the public key to encrypt "My unique identifier is $FOO and I approved this message". Submit that with every request to the web service.
4) The web service decrypts each request, bouncing any which don't contain a valid identifier. You can do as much or as little work as you want here: keep a whitelist/blacklist, monitor usage on a per-identifier basis and investigate suspicious behavior, etc.
5) Since the unique identifier now never gets sent over the wire, the only way to compromise it is to have physical access to the phone. If they have physical access to the phone, you lose control of any data anywhere on the phone. Always. Can't be helped. That is why we built the system such that compromising one phone never compromises more than one account.
6) Build business processes to accommodate the need to a) remove access from a user who is abusing it and b) restore access to a user whose phone has been physically compromised (this is going to be very, very infrequent unless the user is the adversary).
The simple answer is that as things stand today it's just not possible to keep secrets on the iPhone. A jailbroken iPhone is just a general-purpose computer that fits in your hand. There's no trusted platform hardware that you can access. The user can spoof anything you can imagine using to uniquely identify a given device. The user can inject code into your process to do things like inspect the keychain. (Search for MobileSubstrate to see what I mean.) Sorry, you're screwed.
One ray of light in this situation is in app purchase receipts. If you sell an item in your app using in app purchase you get a receipt that's crypto signed and can be verified with Apple on demand. Even though you can't keep the receipt secret it can be traced (by Apple, not you) to a specific purchase, which might discourage pirates from sharing them. You can also throttle access to your server on a per-receipt basis to prevent your server resources from being drained by pirates.
UAObfuscatedString could be a solution to your problem. From the docs:
When you write code that has a string constant in it, this string is saved in the binary in clear text. A hacker could potentially discover exploits or change the string to affect your app's behavior. UAObfuscatedString only ever stores single characters in the binary, then combines them at runtime to produce your string. It is highly unlikely that these single letters will be discoverable in the binary as they will be interjected at random places in the compiled code. Thus, they appear to be randomized code to anyone trying to extract strings.
If you can bear to be iPhone OS 3.0-only, you may want to look at push notifications. I can't go into the specifics, but you can deliver a payload to Apple's servers along with the notification itself. When they accept the alert (or if your app is running), then some part of your code is called and the keychain item is stored. At this point, that is the only route to securely storing a secret on an iPhone that I can think of.
I had the same question and spent a lot of time poking around for an answer. The issue is a chicken and egg one: how to pre-poluate the keychain with data needed by your app.
In any case, I found a technique that at least will make it harder for a jailbreaker to uncover the information - they'll at least have to disassemble your code to find out what you did to mask the info:
String Obfuscation (if the link breaks search for "Obfuscate / Encrypt a String (NSString)")
Essentially the string is obfuscated before placed in the app, then you unobfuscate it using code.
Its better than doing nothing.
David
EDIT: I actually used this in an app. I put a base coding string into the info.plist, then did several operations on it in code - rot13, rotate/invert bytes, etc. The final processed string was used to decode the obfuscated string. Now, the three letter agencies could for sure break this - but at a huge cost of many hours decoding the binary.
I was going to say that this is the best technique I've come across, but I just read Kiran's post on UAObfuscatedString (different answer), which is a completely different way to obfuscate. It has the benefit of no strings saved anywhere in the app - each letter is turned into a method call. The selectors will show up as strings, so a hacker can quickly tell that your class used that technique though.
I think that this similar question, and my answer, may be relevant to your case too. In a nutshell, there was some talk of a trusted platform module being present in an iPhone. This would allow your service to trust an iPhone, even in the hands of an attacker. However, it looks like using the keychain is your best bet.
Did you consider/try the Push Notification suggestion, for initially transmitting the secret to the app & keychain? Or end up finding some other method to achieve this?
I'm going have my iphone app upload images to Amazon S3. Instead of putting the AWS credentials in the app, I am going to have the app phone home to my server for the URI and headers to use in the S3 upload request. My server will generate the S3 URI, proper signatures, etc. I can then implement a tighter, more specific security model on my app's webservice than AWS offers by itself and not give away my AWS keys to anyone with a jailbroken iphone.
But there still has to be some trust (credentials or otherwise) given to the app, and that trust can be stolen. All you can ever do is limit the damage done if someone jailbreaks an iphone and steals whatever credentials are in the app. The more powerful those credentials are, the worst things are. Ways to limit the power of credentials include:
avoid global credentials. make them per-user/application
avoid permanent credentials. make them temporary if possible
avoid global permissions. give them only the permissions they need. for instance, write permissions might be broken down into insert, overwrite, delete, write against resource group A or B, etc, and read could be broken into read named resources, read a list of all existing resources, read resource groups A or B, etc.
I would recommend creating a key at run time if possible. This way if the key were to get apprehended during a particular session, once the session ends, the key will be worthless. They could still apprehend the key from memory if they are smart enough, but it wouldn't matter since the key would become invalid after a period of time.
Sounds wonky. Would use HTTPS and maybe an encryption package to handle the key.
I think CommonCrypto is available for iPhone.
EDIT: Still sounds wonky. Why would anyone pass a secret key in an HTTP header? Anyone who traces your network traffic (via a logging wifi router, for instance) would see it.
There are well-established security methods for encrypting message traffic...why not use them rather than invent what is basically a trivially flawed system?
EDIT II: Ah, I see. I would go ahead and use the Keychain...I think it is intended for just these kinds of cases. I missed that you were generating the request using the key. Would still use HTTPS if I could though, since that way you don't risk people deducing your keygeneration scheme via inspection of enough signatures.