I have searched IT Security and Google for something similar to this, but wasn't able to find anything remotely related to what I'm doing.
I'm developing software which has 2 parts - a C# program run on a single, secure, trusted computer, and PHP software running on a server. This system deals in sensitive data, namely pharmacy records (not in the US, HIPPAA doesn't apply).
I want to securely encrypt the data, so that even in the case that the database is stolen, as little of the data can be decrypted as possible. I'm already protecting the data by not storing any identifiable data like Name, Address etc, save for an email address.
I initially wanted to use a variant on this solution, however on further contemplation I realised that RSA was not an appropriate way to encrypt plaintext directly. My research led me to believe that AES is the most appropriate algorithm for that. I know that the advice given to most people who are not experts on encryption is to follow an industry-standard protocol, however I was not able to find one which matched my criteria.
The criteria are:
- For each user's data, only the user himself should be mathematically able to access his data given the contents of the server - meaning a key derived from his password is used (the C# software has full access to all users' data, it can have access to the keys)
- Decryption should not be possible having obtained solely the contents of the server
- Plaintext data should never be stored on the server (therefore I want to encrypt in the C# software)
- Data needs to be able to be encrypted without having the user available to provide his password
- Data will only be decrypted and read in PHP - no new data or modified data will need to be re-encrypted and written
- Only a hash of the user's password can be stored or accessed
Here is a solution I have come up with:
Naturally, all connections are made through TLS/SSL (over HTTPS). Before any sensitive data is transferred, the server and software are "primed" or paired. An asymmetric key pair is generated on the server, and the private key transferred to the software (I refer to the C# component as "the software"). The private key is deleted from the server, and the public key stored.
When a user registers, their password is used to generate a 128-bit key using PBKDF2. This key is RSA-encrypted using the previously generated public key and stored.
When data is uploaded from the software onto the server (every 24h), the software sends a list of user ids it will be uploading data for (over HTTPS of course). The server sends back a list of the RSA-encrypted 128-bit keys along with the corresponding user ids. The software decrypts them one-by-one using its private key, obtaining a list of 128-bit keys. For each user, the server takes that user's data and encrypts it with AES-128 using that user's corresponding key. The whole payload is uploaded to the server and directly stored.
When a user logs in, their password is accessible for a short time, and PBKDF2 is used to generate their AES-128 key. To prevent them from having to re-enter their password on each page load, the AES-128 key is stored in a secure cookie on their machine with a short (5-10min) expiry time and used on subsequent page loads to decrypt and display that user's data. It's not actually stored on the server at any point.
Is this security protocol appropriate? Should I modify it? Is there anything which is industry-standard and would work here? Any help would be greatly appreciated.