I am working on a system that needs to keep the data safe and not accessible to people without authorized access. The client is a web app that communicates with the servers via APIs. This is what I have so far:

 __________            _____________            __________
|  Server  |          |    Server   |          |  Server  |
|  (Keys)  |          | (Web Files) |          |  (Data)  |
|__________|          |_____________|          |__________|
     |                       |                      |
    SSL                     SSL                    SSL
     |                       V                      |
     |                  __________                  |
     --------------->  |  Client  |  <---------------
  • Server (Web Files) servers the static files
  • Server (Data) connects to DB (Data) and servers the encrypted data
  • Server (Keys) connects to DB (Keys) and serves the user’s data key

The process would be:

  1. Client is served the static files by Server (Web Files) via SSL
  2. Client authenticates using Username/Password with Server (Keys) and gets their data key via SSL
  3. Client connects to Server (Data) and gets the encrypted data via SSL
  4. Client decrypts data using the acquired data key
  5. Client alters the data
  6. Client encrypts the data using the acquired data key
  7. Client sends the encrypted altered data to the Server (Data) via SSL

This way each server is isolated, but if someone gains access to Server (Keys), they can work their way to decrypting the data in Server (Data). Is there a way to make this more tight, so as if one of the servers or DBs is compromised, it would not compromise the security of the data? The current configuration is convenient but not set in stone.


  • The customized and obfuscated encrypt/decrypt library is out of the window.
  • The data would be private info and their security is mandated by the government with the very broad and vague “Private information should be protected against leakage and unauthorized access”.
  • Up until now, the system was isolated and was operated within a closed network, locally (with the same design). We now need to allow broad remote access.
  • If we turn over the encryption key to the client users, they become responsible for its safety and if they lose it, the data becomes inaccessible. If we need to be able to retrieve the data, we need to save the key on our servers as well (maybe by encrypting it with a master key, and make the retrieval process manual, instead of automatic).
  • It is back to the drawing board.
  • 4
    Your keys are already compromised; the browser needs them to decrypt your data, and anyone can use Firebug or some similar tool to inspect them in the browser. SSL avoids this problem by using asymmetric encryption (public and private keys). Instead of rolling your own security system, you should probably use one that the experts have already designed to be secure, like OAuth. – Robert Harvey Dec 14 '17 at 17:56

At a high-level, the overall approach seems basically sound but you've added a lot of complexity here that doesn't seem to improve security. The more complicated you make things, the more difficult it will be to verify that you don't have vulnerabilities. It also increases the chance that you will make a mistake.

Client is served the static files (including a customized and obfuscated encrypt/decrypt library) by Server (Web Files) via SSL

This is a little concerning. Customized how? Don't roll your own security.

It's really not clear what putting keys on a separate server buys you. An attacker will only have one server it needs to compromise. I don't see any significant difference in just controlling access to the data server.

Ultimately the weakest links in this (and many other) designs is the use of passwords for authentication. Password are commonly leaked or cracked because of weak hashing. Whether the attacker needs to access one or 1000 servers, they still only need to figure out a single password and it's game over. If you are really looking to improve security, consider using a asymmetric encryption from the client as well. For example, if you used client-certs here, you could encrypt the data on the server using the client's key*. Then no one else would be able to decrpyt it, including the server. It's not clear what exactly your goals are with this design though.

*This leads to questions about how the client manages their keys.


If you are concerned about the keys being compromised, one problem is that your server is storing plaintext keys. That is problematic for the exact same reasons why storing plaintext passwords is problematic.

The difference is that for passwords, it is sufficient to store their hash. But the user will need to get the plaintext key.

One possible solution would be for users to encrypt and decrypt their key with a passphrase, so that the key server never sees the plaintext key. Depending on your definition of “secure”, this means the key passphrase must never be transmitted to the server. When I say “encrypt the key with a passphrase”, this doesn't mean you should XOR the key with a literal passphrase, but should use a key stretching algorithm to derive a key from the user's passphrase.

The similarity to passwords is that this encryption will not be impenetrable when the encrypted keys are compromised. Hashed passwords and encrypted keys can be cracked. Because the passwords (incl. the passwords encrypting the keys) tend to be weak, this only buys some time on average before the attacker obtains a plaintext key. During this time, users will have to decrypt the data with their old, compromised key and re-encrypt it with a new key.

If you need more security (for some definition of “security”), then don't store these keys at all. The key should never leave the user's devices.

Note that the static web server is a huge security risk, probably even more so than the key server. The code served from this server will operate on plaintext keys and plaintext data on the user's device. If this code were to be replaced with a malicious implementation that exfiltrates the keys or data, most users would not be able to notice.

If you have extremely sensitive data, using a key escrow scheme is not going to be sufficiently secure. Performing the decryption on a network-connected device is also questionable.

If you have more ordinarily sensitive data, then all of this sounds like tremendous overkill. All of that crypto is complexity, and complexity breeds bugs. In the context of security and crypto, even small bugs or side channels can be game over.

Instead, prefer well-understood solutions that have mature tooling support. For you, that likely means users log directly into the data server using usernames+passwords. You should couple that with rate limiting, monitoring, and intrusion detection solutions. It is easier to secure a single server than it is to secure every client connecting to that server. This provides a good argument for serving plaintext data from the server. Only serving encrypted data has marginal value, assuming the clients trust you (which they do, if you would be able to store their plaintext keys).

  • Thank you, I missed the error of plaintext keys. I will try and find a solution using client stored keys and I will move away from browsers. The convenience is not worth the compromise. The only problem with client stored keys is that once the key is lost, the data becomes unretrievable. – Basilis P. Dec 15 '17 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.