Storing Encryption Key Locally for Disconnected Mode - security

I need to store an encryption key locally in order to allow a user to use my CouchApp in a disconnected mode. The data that I will be sending is very sensitive and requires encryption by law. However, we would like to offer full access to data when running disconnected. Currently we have a password key generator, but this would require the user to enter their password every time they want to view a record. Also this doesn't seem to be secure as an experienced/advanced user could potentially access the encryption key, and then the Local Database. I'm basically wondering if anybody has experience with the disconnected security model, or if you can offer any pointers on how to allow access while maintaining security.

If your client is connecting directly to the database then all users have access to the entire data set. Apparently you trust your users... with everything. This feature right here breaks the most common data protection models. An attacker doesn't need sql injection or insecure direct object reference, he can just grab whatever he because you are giving him everything.
I don't see how cryptography solves your problems. It looks like a textbook CWE-602 violation.

Related

is client based online encryption practical?

I'm wondering whether a mechanism exists that allows client to client encryption. For example, when enabled, any information that is entered on one client can only be decrypted using a specific key.
Similar to how regular public key transactions work, but server agnostic.
A use case:
Everything on my Facebook profile is encrypted, and no body would be able to view that information (not even facebook). The users that I give the key would be able to decrypt that information.
This would allow complete control of data stored online.
The same idea can be applied for pictures uploaded to the internet.
One issue that I see is to have a practical mechanism to manage keys and a secure way to distribute keys to other users.
Has anyone done something like this before?
In case of Facebook I can imagine encrypting the data with OpenPGP keys into armored (text) format. Then you can place encrypted block to facebook or anywhere else. Other users would take the block, decrypt it on the client side and see it.
The same applies with other social networks and places where you can store some text block.
You can easily do encryption in some client application and even in Javascript (if you manage to make JavaScript load local user's keys somehow).

How can you encrypt users' data server-side without ruining the experience?

Many users – myself included – would like the security of having everything they do on a web service encrypted. That is, they don't won't any one at the web service to be able to look at their: posts, info, tasks, etc...
This is also major complaint in this discussion of an otherwise cool service: http://news.ycombinator.com/item?id=1549115
Since this data needs to be recoverable, some sort of two-way encryption is required. But unless you're prompting the user for the encryption key on every request, this key will need to be stored on the server, and the point of encrypting the data is basically lost.
What is a way to securely encrypt user data without degrading the user experience (asking for some key on every request)?
-- UPDATE --
From #Borealid's answer, I've focused on two possibilities: challenge-response protocols, where no data (password included) is sent in the "clear", and non-challenge-response protocols, where data (password included) is sent in the "clear" (although over HTTPS).
Challenge-response protocols (specifically SRP: http://srp.stanford.edu/)
It seems that its implementation would need to rely on either a fully AJAX site or using web storage. This is so the browser can persist the challenge-response data during encryption and also the encryption key between different "pages". (I'm assuming after authentication is completed I would send them back the encrypted encryption key, which they would decrypt client-side to obtain the real encryption key.)
The problem is that I'm either:
fully AJAX, which I don't like because I love urls and don't won't a user to live exclusively on a single url, or
I have to store data encryption keys in web storage, which based on http://dev.w3.org/html5/webstorage/ will persist even after the browser is closed and could be a security vulnerability
In addition, as SRP takes more than one request ( http://srp.stanford.edu/design.html ), there needs to be some persistence on the server-side. This is just another difficulty.
Traditionally
If I'm ok transmitting passwords and data in the clear (although over HTTPS), then the client-side issues above are not present.
On registration, I'll generate a random unique encryption key for the user, and encrypt it using their password and a random salt.
In the database, I'll store the user's password hash and salt (through bcrypt), encrypted encryption key, encryption key salt, and encryption iv.
After an authentication, I'll also need to use their password to decrypt the encryption key so that they may view and enter new data. I store this encryption key only temporarily and delete it when they explicitly "log out".
The problems with this approach is that (like #Borealid points out) evil sysadmins can still look at your data when you are logged in.
I'm also not sure how to store the encryption keys when users are logged in. If they are in the same data store, a stolen database would reveal all data of those who were logged in at the time of theft.
Is there a better in-memory data store for storing these encryption keys (and challenge data during an SRP authentication)? Is this something Redis would be good for?
If the data need to be recoverable in the event of user error, you can't use something like a cookie (which could get deleted). And as you point out, server-side keys don't actually secure the user against malicious sysadmins; they only help with things like databases stolen offline.
However, if you're running a normal web service, you've already gotten pretty lucky - the user, in order to be unique and non-ephemeral, must be logged in. This means they go through some authentication step which proves their identity. In order to prove their identity, most web sites use a passed credential (a password).
So long as you don't use a challenge-response authentication protocol, which most web sites don't, you can use an encryption key derived from a combination of a server-side secret and the user's password. Store the encryption key only while the user is authenticated.
If you do this, the users are still vulnerable to sysadmins peeking while they're using the service (or stealing their passwords). You might want to go a step further. To go one up, don't send the password to the server at all. Instead, use a challenge-response protocol for authentication to your website, and encrypt the data with a derivative of the user's password via JavaScript before uploading anything.
This is foolproof security: if you try to steal the user's password, the user can see what you're doing because the code for the theft is right there in the page you sent them. Your web service never touches their data unencrypted. This is also no hindrance to the normal user experience. The user just enters their password to log in, as per normal.
This method is what is used by Lacie's storage cloud service. It's very well done.
Note: when I say "use foo to encrypt", I really mean "use foo to encrypt a secure symmetric key which is then used with a random salt to encrypt". Know your cryptography. I'm only talking about the secret, not the methodology.
None of those other solutions are going to maintain the feature set requested -- which specifically wants to preserve the user experience. If you look at the site referenced in the link, they email you a nightly past journal entry. You're not going to get that with JavaScript trickery per above because you don't have the browser to depend on. So basically this is all leading you down a path to a degraded user experience.
What you would want, or more precisely the best solution you're going to find in this space, is not so much what wuala does per above, but rather something like hush.com. The handling of user data needs to be done on the client side at all times -- this is generally accomplished via full client-side Java (like the Facebook photo uploader, etc), but HTML/JavaScript might get you there these days. JavaScript encryption is pretty poor, so you may be better off ignoring it.
OK, so now you've got client-side Java running a Journal entry encryption service. The next feature was to email past journal entries to users every night. Well, you're not going to get that in an unencrypted email obviously. This is where you're going to need to change the user experience one way or the other. The simplest solution is not to email the entry and instead to provide for instance a journal entry browser in the Java app that reminds them of some old entry once they get to the website based on a link in the daily email. A much more complex solution would be to use JavaScript encryption to decrypt the entry as an attachment inline in the email. This isn't rocket science but there is a fairly huge amount of trickery involved. This is the general path used by several web email encryption services such as IronPort. You can get a demo email by going to http://www.ironport.com/securedemo/.
As much as I'd love to see a properly encrypted version of all this, my final comment would be that journal entries are not state secrets. Given a solid privacy policy and good site security semantics, I'm sure 99% of your users will feel just fine about things. Doing all this right with true security will take an enormous amount of effort per above and at least some design/UE changes.
You should look into the MIT project CryptDB which supports querying an encrypted database using a subset of SQL. (see the forbes article, mefi thread, or Homomorphic encryption on wikipedia)
There is the Tahoe-LAFS project for cloud storage too, which conceivably could be leveraged into a fully anonymous social networking application, one day in the distant future.
If you want to perform computations on a server without even the server being able to see the data, you may be interested in knowing about fully homomorphic encryption. A fully homomorphic encryption scheme lets you perform arbitrary computations on encrypted data, even if you can't decrypt it. However, this is still a topic of research.
For now, I guess your best bet would be to encrypt all posts and assign meaningless (e.g. sequential) IDs to each one. For a more in-depth discussion of how to encrypt server-side data with today's technology, look up.

How to verify an application is the application it says it is?

Here's the situation: we have a common library which can retrieve database connection details from a central configuration store that we have setup. Each application uses this library when working with a database.
Basically, it will call a stored procedure and say "I am {xyz} application, I need to connect o " and it will return the connection details for that applications primary database (server, instance, database, user, and password).
How would one go about locking that down so that only application {xyz} can retrieve the passwords for {xyz} databases (there is a list of database details for each application... i just need to secure the passwords)?
The usual way is to have a different config store per app and give each app a different user/password to connect to the config store.
That doesn't prevent anyone from changing the app and replacing the user/password for app X with the values from app Y but it's a bit more secure, especially when you compile this data in instead of supplying it via a config file.
If you want to be really secure, you must first create a secure connection to the store (so you need a DB drivers that supports this). This connection must be created using a secure key that is unique per application and which can be verified (so no one can just copy them around). You will need to secure the executable with hashes (the app will calculate its own hash somehow and send that to the server who will have a list of valid hashes for each app).
All in all, it's not something trivial which you can just turn on with an obscure option. You will need to learn a lot about security and secure data exchange, first. You'll need a way to safely install your app in an insecure place, verify its integrity, protect the code against debuggers that can be attached at runtime and against it running in the virtual machine, etc.
Off the top of my head, try PKI.
Are you trying to protected yourself from malicous programs, and is this a central database that these applications are connecting to? If so you should probably consider a middle layer between your database and application.
I'm not sure this applies to your case, depending on how what your answers to the abovementioned would be, but by the comments it sounds like you are having a similar case to what this question is about.
Securing your Data Layer in a C# Application
The simplest/most straightforward way would be to store the passwords in encrypted format (storing passwords in plaintext is just plain bad anyhow, as recently demonstrated over at PerlMonks) and make each application responsible for doing its own password encryption/decryption. It would then not matter whether an app retrieved another app's passwords, as it would still be unable to decrypt them.
One possibility is to keep the passwords in the database in an encrypted form, and convey the encryption key to the allowed application(s) in a secure connection.Then, only the application with the encryption key can actually get the passwords and not others.

Encrypting 3rd party credentials

I have an application where I need to store 3rd party credentials to services like Amazon S3, FTP, SFTP, etc..
I know that it is possible to access some of those systems without passwords, but that has its own issues. If our customers gave us access to their S3 buckets via ACL we would still need to verify which bucket belongs to which user, same goes for SFTP and ssh key auth.
We will try our best to allow non-password alternatives where possible, but sometimes (FTP) it just won't be possible. Therefor I am looking for advice on how to store this sensitive data in our database (MySql) or elsewhere.
In the past I have read about people using TrueCrypt partitions that automatically unmount, but that would probably require decent intrusion detection. For now I'm interested in simple approaches that lead to reasonable security and can improved upon in the future.
Any advice on the subject would be highly appriciated!
There are a range variety of possibilities and since in my opinion you provide not enough info about the context, i will try to give you an overview from my point of view. I assume that here the most important aspect is confidentiality of your data and and authentication of the users. Integrity and availability of data is much less important.
If you want basic security, you can let MySQL handle it by means of username/password combinations and set access rights on the given account. However, since the access control mechanism of mysql is not fine-grained (you can set access control rules per table only, not per row) this will probably yield a bad database design.
If you want to have a non-password approach, you can give users client-certificates and let them prove their identity by presenting their client certificates (use TLS for that) or let them sign something (note their are dangers because you create a so called signing oracle).
Another approach is to encrypt your data in the database. You can do that by deriving a symmetric key from the password and encrypt the credentials with this data. The catch here is of course that your key derivation protocol should be good and this is not easy to accomplish (so if you choose this, i advice you to take existing key derivation protocols or use a streamcipher). Take a look here for a list of streamcipher http://en.wikipedia.org/wiki/Stream_cipher .
If you care very much for security you can start thinking about fancy solutions like authentication with smartcards, or a time synchronized tamper resistant device for generating acccess codes. However, note that these fancy solutions do not give you free security, implementing such systems if hard and costly (due to development and deployment) however, if done correctly they provide the best security.
Have the user supply a (strong) password when they set up an account (before they provide their passwords). Then encrypt all data for that account within your database using a key derived from a strong hash (SHA256 or something like that) of the user's password. That way if your servers get compromised, no data will be revealed because it is encrypted with the user's password (well, a hash of the user's password) and that password is not stored anywhere on your server.
You need to investigate the use of keystores. TruCrypt is an example of such a keystore, but this is a personal keystore, not intended for service level credentials.
You won't be able to avoid storing their passwords in a format that someone can get access to, the goal is to minimize who can access the information. Putting in the same MySQL as application data is asking for disaster.

Ok, so I've encrypted my data now where do I hide the key?

I have a database that contains sensitive information. I can encrypt / decrypt the data on the read write operations. The problem is that I need to store the key in the application. If someone has hacked their way in such they have access to the database then they can also grab the application (java) decomplie it and pull the key.
This seems like a speed bump at best. What other solutions are available?
The only thing you can do is make it difficult to extract the key from your application. You can't make it impossible. If you give someone a box with contents that you're trying to protect, you have to give them the key if you want them to be able to access the contents. Once you give them the key they can do whatever they want… if they take the trouble of finding the key.
This is a case of Bob and Eve being the same person, you want to give Bob access but stop Eve from seeing it.
This is DRM, it doesn't work.
I am assuming you have some way to verify the credentials of the user before allowing them to access the database?
Usually the architecture for these kinds of things is as follows:
Database
Server
Client
The Client connects to the Server, which then connects to the Database.
The Server makes sure the Client authenticates correctly before allowing them access to sensitive information. The decryption key is stored only on the server. Noone should have access to the server, and especially the file that contains the key. This way the clients do not have any encryption/decryption they have to do, and do not have to store any keys.
Read up on keystores.
Require the user to enter a passphrase to access their data. Burying the key in the code is security by obscurity.
Store the keys in a CSP container. Consider the Java CSP here .
This is IMO the safest way possible. But you can also consider storing the key in a file which is protected by the operating system using some kind of ACL.
require the user to log in using a strong password; use the password as the key for a symmetric encryption algorithm to decrypt the asymmetric database key
keep the db key in secure memory while the application is running (if that is an option)
Encrypt the key (using DPAPI), put it in a file, put an ACL on that file etc...

Resources