I hope this isn't too blunt, but the task you are undertaking here is extremely difficult, and the odds of you getting it right are slim. Security flaws are most of the time caused by mistakes in implementation, not in the underlying technologies. In order to make a system like the one you've described secure, you have to use the correct tools and the correct methodology and account for all of the edge cases or the security of the entire system will be compromised.
That's not really a helpful answer though, is it? When you are building a system like you are building the question you should be asking shouldn't be "How do I do this?" It should instead be "What is the way I can do this that relies the least on myself?" The answer to that question is to use tried and tested systems wherever possible, and to roll your own solutions only as a last resort.
To answer your first point about encryption, it doesn't make sense to worry too much about securing a key in memory of the server. If an attacker has enough access to a machine to read your keys out of memory, you are totally and completely hosed and any solutions that you have coded up aren't going to help much any way. In other words, favor securing data at rest and data that is moving over the internet, since that is where most attacks are going to occur.
As far as storing the data goes, I don't see any reason why asymmetric crypto needs to be involved here. I would use something like PBKDF2 to derive a key directly from the user's password, then encrypt the data and store the encrypted blob in a database. I would recommend a database over a flat file because managing a folder full of flat files is tedious at the best of times. Databases may not show any solid benifits in speed or security over flat files, but they come with many other features such as pooled connections and they also make backing up data much easier than flat files. Use the simplest system you can to minimize your attack surface, and use thoroughly tested open source tools whenever possible. If you can find a way to use GPG for the encryption and key derivation part of things, I would recommend it.
As far as transfer goes, I believe that you are thinking about things the wrong way. Don't do any encryption client side. Browser javascript is not suitable for cryptography, as explained in this article. So long as you make sure that you use TLS/SSL for all connections to your site, you shouldn't need to worry about transmitting data unencrypted. For an example of why it is hard to do client side encryption, do some googling about the security of MegaUpload's successor, MEGA.
Finally, I wouldn't trust any one dude you get an answer from on the internet, including myself. I would do a lot of research about this sort of thing before committing to a solution. Also, I might recommend asking this question over at the IT Security Stack Exchange.
-- EDIT --
Somehow, I totally missed the fact that there are three parts to your system, the client (browser), the server (database), and the connector that imports data from the VisualFox Database. This actually makes the whole system a lot more complex, because there are essentially three parties that need to share a secret, instead of two. What I would recommend is not to encrypt the data based on the users password, but to instead encrypt it based on some server password. I'm having a little bit of trouble thinking of a good way to describe this process, so I'll give you an example workflow instead.
Server Side
- Admin starts server.
- During start up, server code asks for a password.
- Server uses PBKDF2 to derive a key which is stored only in memory.
- Server spawns a thread that will poll the VirtualFox Pro server every X (days/hours/minutes) for updated data.
- Server enters loop awaiting requests from browser clients.
Updating database
- Main Server's child thread requests an update of data from the Virtual Fox Pro server.
- VirtualFox Pro server dumps a report containing data for client's with modified entries.
- VirtualFox Pro server opens secure connection to main server (ssh, sftp, etc) and transmits zipped data.
- One by one, the main server uses the PBKDF2 derived key that is stored in memory to decrypt blobs stored in a database, update them with new data, reencrypt them, and store them back into the database. This process should all happen in-memory.
Browser client connects
- Main server receives https request from client.
- Main server uses some third party authentication framework to check clients credentials. This framework should use bcrypt to hash passwords and only store the hashes on the file system.
- If the authentication framework positively identifies a user, the main server will decrypt the user's blob using the PBKDF2 derived key in memory and send the data to the user.
- When the user's authentication cookie expires, the main server will stop using the PBKDF2 derived key to decrypt data, and will instead prompt the user to re-authenticate.
This model is more in line with how traditional websites work (which means that you can rely on third party, bug tested frameworks), but data is encrypted/decrypted in memory before touching the database. Ideally, you could use GPG or some other keystore for managing the encryption keys on the main server as well.
I'm going to start off with a slightly dickish response, namely, if you are uncertain about this stuff you should focus on finding a (reputable) library that will handle these sorts of things for you. I'm not all that familiar with Unity, so if such a library exists, I hope someone else can provide an answer pointing to it. As I'm sure you are aware, even major corporations mess these kinds of things up.
That said, I don't really understand from whom you are trying to protect this data. (I also don't understand why this would be sensitive but that's not important.) As far as I can tell the PlayerPrefs are stored locally so the kinds of attackers you are considering are 1) other applications on the device, 2) other users on the device, 3) attackers with physical access to the persistent memory e.g. the SD card. Most of these are already protected against via operating system mechanisms. But to be completely clear, doing encryption yourself will increase protection beyond what the operating system is doing. The argument comes down defining a threat model and doing the cost-benefit analysis of mitigating the threats. The cost-benefit analysis will include the development and maintenance costs for you, and the key management costs for the user, e.g. if the user loses their key, they lose their data and nothing can be done about it.
Addressing your second to last paragraph, if you just stored the symmetric key with the encrypted data you would have no security. You might as well store the unencrypted data.
Your four step scheme should work (though there are details you need to get right), but it seems to be overkill. If the symmetric key is encrypted, then I'll need to have access to the private key to decrypt it. If I can securely store the private key, why don't I just store the symmetric key where I store the private key? Alternatively, unless it is a large amount of data, why not just encrypt the data directly with the private key? Or even, if I can store keys securely, why don't I just store the data there?
I only see something like your four step procedure being useful if the asymmetric keys are managed by the OS but no symmetric key management is provided, and you need to encrypt large amounts of data. In fact, decent crypto libraries will usually handle automatically generating a symmetric key and storing it encrypted with the ciphertext so you don't have to worry about it and you don't need to worry about size limitations or performance.
Best Answer
While I don't know of any books/papers that discuss this exact problem, it seems to me that any solution to "the synchronization problem", paired with any solution to "the avoid-re-encrypting-file-with-new-key problem", should solve your original problem. Each of those sub-problems have several solutions.
The synchronization problem
You have one "common file" (in this case, a symmetric key) that, ideally, you want to be the same across all devices. However, for one reason or another, the data is somehow different from one device to the next -- split-brain syndrome -- and you want all the devices connected to the network to somehow reach a consensus as to whether to use version A from now on, or use version B from now on, or perhaps some entirely new version C from now on.
There are three popular approaches:
One of many possible solutions goes like this:
In particular, if every device has a different version of this file, then the "birthday problem" practically guarantees that, after enough iterations of this algorithm, eventually 2 devices will pick the same version of the file, and eventually all the online devices will converge on the same version of the file.
The avoid-re-encrypting-file-with-new-key problem
As I understand it,
The standard way of doing that is to store the data in OpenPGP format (as standardized in RFC 4880). a b c d e
You already have one layer of indirection -- a person types a passphrase, which is used to decrypt the device-specific password.
The OpenPGP process uses a second layer of indirection: Every file is encrypted with its own unique symmetric key.
It works something like this:
Every time new data is created or edited, a completely new symmetric key is generated, the new key itself is encrypted with the user's public key and that encrypted key is stored in the header of the encrypted file. The data is encrypted with that new symmetric key and stored afterward in that encrypted file. (This can all be done before the device ever connects to the network).
Later that encrypted file is synchronized unmodified over the network. (Except the sender somehow obtains the receiver's device-specific key, encrypts the file-specific symmetric key with the receiver's key, and then adds that encrypted key to the file header).
To decrypt that file and read the data,
To make the system easier to change/migrate,
Use an encrypted file format (such as OpenPGP) that specifies exactly which encryption algorithm was used for this particular file. That allows future software to detect which encryption algorithm was used to create a particular file. Then the device can decrypt today's shiny new files using today's shiny new preferred algorithm. The device can also decrypt dusty old files with yesterday's dusty old algorithms -- and optionally re-encrypt using today's shiny new preferred algorithm.
Use an encrypted file format (such as OpenPGP) that allows you to store the particular file-specific symmetric key in the header several times, each time encrypted with a different public key or device-specific key.
When a user changes the passphrase, only the device-specific key gets re-encrypted, just like what you are doing already.
If for any reason the device-specific key needs to change, then the device must re-encrypt the file-specific key in the header of each and every encrypted file it holds. That's probably faster than decrypting and re-encrypting the entire file.
Have you considered using some off-the-shelf implementation of OpenPGP, such as "Pretty Good Privacy" or "GNU Privacy Guard"?