I know there have been a few questions about this already, but I just wanted to know if anyone can take a look at my design plans to see if there are any gaping security holes. I am in the process of making a web application which securely stores sensitive information that can then be retrieved by staff members who have access to it.
I have two servers - a main server and a decryption server. The main server stores the encrypted data, authenticates the users, outputs the HTML, etc. The decryption server only stores a partial private key and does the decrypting when the partial key is combined with the other half stored on the main server. Of course, everything is done over SSL, even between the two servers. Other limitations will be in place between the two servers, such as restricting only to those two IP addresses as well as limiting the number of decryptions to a certain number (e.g. one every 15 seconds and everything else gets queued - self destruct if the queue reaches a certain number and require admin intervention).
The functionality I am looking for is to have anonymous users able to encrypt new data into the database through the website, all staff members to be able to update existing entries and privileged staff members to be able to decrypt stored data.
Summary of keys and hashes used
Edit - For clarity, there are only two types of keys. Both are asymmetric. I have changed this post and simply called them key1 and key2 for simplicity. Key2 will be xor'ed into two parts, key2a and key2b which combine again to create key2. Key1 is a key encrypting key which encrypts key2. Key2 is used to decrypt the sensitive information.
- User password hashes used for authentication, stored in the database.
- Key1 - Key encrypting key stored temporarily in RAM and stored permanently on the administrator's personal computer and/or flash drive at a completely different location and network
- key2a keys - Partial private keys stored in database encrypted by the key encrypting key mentioned above (key1).
- Both public keys for the two private keys above are stored in plain text in the DB.
- Key2b keys - Other halves of the aforementioned partial private keys
- Key encrypting key (key1) can be generated essentially anywhere, probably on the administrator's own PC.
- The other key pair (key2) is generated by the main server, one for every piece of information to be encrypted.
The encryption process is as follows:
- A new key2 private and public key pair is generated (a different key pair per sensitive datum)
- The information is encrypted using key2's public key and stored in the database
- Key2's private key is then xor'ed into two parts (key2a and key2b).
- key2a is encrypted using key1's public key and stored in the database
- key2b is sent to decryption server
- Decryption server stores key2b in its database and sends back insert ID
- Insert ID stored in main db
- key1 (key encrypting key) stored in memcache (or redis). An administrator must upload this key manually. It will be generated on their own computer. It is stored temporarily in the RAM (until the server goes down) and permanently stored offline on the administrator's computer or flash drive.
- Non-admin staff member authenticated with their own username and password
- If they have permission, they can retrieve key1 from the memcache server
- key1 decrypts the stored half private key key2a
- key2a and the encrypted data are sent to decryption server along with the respective insert ID
- Decrypting server then combines key2a and key2b to create key2
- Key2 then decrypts the information and send it back to the user
- For key rotation, the decrypted information is then reencrypted using a new key2 pair as outlined in the encryption process
Full key rotation (initiated from decryption server)
I'm not sure if this is necessary, but these are my thoughts. One thing that doesn't sit well with me is that ALL of the data will be momentarily unencrypted (at least in the memory) of the decryption server. As well, I would have to give this server free access to the encrypted data and keys from the main server, which could also open up a whole other can of worms and would basically be game over if this server were ever compromised. I also address this in one of my questions below:
- Decryption server logs in to main server and requests a full dump of all encrypted data
- A new key1 key encrypting key pair is generated on the decryption server
- All encrypted data is decrypted using the old key1
- A new key2 pair is generated for each piece of decrypted data from the previous step and the data is reencrypted with this key. These are xor'ed into new key2a and key2b.
- New key2a reencrypted using the new key1
- Array of newly encrypted data, new key2a and respective ids are sent back to main server and stored directly into DB
- On main server, new key1 is saved into memcache
- key1 will need to be sent somehow to the administrator as well so that they can restart the memcache server when it goes down. Since the administrator should have the old key1, perhaps encrypting the new key1 with the old key1 and then simply emailing it to the admin would suffice.
A few things I am unsure about:
- Is using memcache to store a private key encrypting key secure enough? If not, I'm open to other ideas.
- For key rotation, is it good practice to rotate all of the keys periodically (both key1 and all key2s) as I have outlined in the "full key rotation" part above, or simply rotate key2s upon use since it is a different key2 for each piece of encrypted data?
Edit :: To answer D.W.'s questions below, I'm not exactly sure how to create a threat model, but I'm assuming you're basically wondering what I am trying to protect against. To be honest, I'm not sure. Essentially, I want only authorized staff members to be able to obtain decrypted data, so whatever that entails, that is what I want to protect against. If either of the servers were compromised, I would want the effect to be either completely mitigated or at least minimized. For example, if someone were to hack the decryption server, they would still need the encrypted data and a partial decryption key. If someone were to hack the main server, they would need the key encrypting key which will be erased from memory if the server goes down; and if the server is still up, they will be limited to a small number of requests per second.