
Ask HN: The way to encrypt and protect sensitive data in database - flashu
Hey!<p>I would like to create a feature in an existing application where users can keep very sensitive data. I need a solution to encrypt and protect data from leakage in case of unauthorized access to the machine(s) and&#x2F;or application bug which can expose the data.<p>I was thinking about a simple solution to encrypt data using the non-shared key generated per user (to avoid decryption of the whole dataset using one key) and keeping those keys in some kind of vault. But the thing is there must be a place and time when those keys are revealed to decrypt data from database&#x2F;storage. The app itself is written in PHP, so I came to another idea to use ionCube or Zend Encoder to protect the file with cypher keys, but the question is: is it safe enough?
======
pmontra
I won't answer directly, please don't be upset.

Did you already perform a threat analysis and a risk assessment?

Who are you defending against? Which are the attack or data breach scenarioes?

Put them in a impact / likelihood matrix and defend against the most serious
combinations.

Do you still need to encrypt live data in the db?

If positive, an approach I used in the past was to never perform any operation
in the server. Users were storing their private key in the browser (local
storage) and decrypt data on the fly in JavaScript (you have to trust the
browser js engine bugs.) The server could generate and store data for them
using the public keys but nothing more.

If you need server side aggregations you can store in cleartext site parts of
the encrypted information. Example: city names give you users per cities,
regions states, countries.

Be careful about reidentification using extra information attackers could know
about your system and users.

~~~
flashu
Thank You for the reply!

I think I've made some mind shortcuts and now I see them after reading Your
questions.

The thing is that I have to access data stored in the encrypted
database/storage because it must be accessible by an application process
without any interaction from the user. Data will be decrypted on-demand by
background worker using the key which I have to store somewhere and which must
be secured somehow and available only for that process.

So far, my idea is flying over solutions like ionCube / Zend Encoder to
encrypt/encode/secure the source code of the application or only parts of it
to prevent exposing the logic responsible for getting out the data among with
keys themselves.

Can I call it: poor-man encryption? :-)

------
mooreds
It's unclear to me if you are trying to encrypt the days in transit, in memory
or at rest?

I don't know anything about your environment but if I were in AWS I would be
using KMS; this blog post walks through it:

[https://blog.koan.co/securing-customer-data-with-kms-and-
env...](https://blog.koan.co/securing-customer-data-with-kms-and-envelope-
encryption-in-node-js-b61983ddaa98)

~~~
flashu
Hi, I am trying to encrypt at rest. I would love to use AWS and KMS, but I
won't be using public cloud for that :( The app will run on VPS-like setup
(DigitalOcean or similar)

~~~
mooreds
Hi,

You can still use KMS even if you are hosting on a VPS. You don't need to send
your data across the internet, just your key requests. All of the major cloud
providers have implementations of encryption services:

AWS: [https://aws.amazon.com/kms/](https://aws.amazon.com/kms/) Azure:
[https://azure.microsoft.com/en-us/services/key-
vault/](https://azure.microsoft.com/en-us/services/key-vault/) GCP:
[https://cloud.google.com/kms/](https://cloud.google.com/kms/)

Open source alternatives (but I'd recommend using a hosted solution as
maintaining one of these might be a bear):
[https://github.com/cloudflare/redoctober](https://github.com/cloudflare/redoctober)
,
[https://github.com/StackExchange/blackbox](https://github.com/StackExchange/blackbox)

------
mtmail
A separate database/vault for user encryption keys is also useful for backups.
This way you can delete (well make it un-decryptable) user data individually
on cold storage. Known as [https://en.wikipedia.org/wiki/Crypto-
shredding](https://en.wikipedia.org/wiki/Crypto-shredding)

------
chatmasta
I'm implementing something similar right now, using parse-server. parse-server
is the application layer in front of a mongo database, through which all
read/write operations transit. parse-server uses "triggers" like "beforeSave"
and "afterFind" that can modify the object(s) or request(s) made by or
returned to the client.

I am using beforeSave to encrypt objects, and afterFind to decrypt them, using
envelope encryption via AWS KMS. There is one customer master key (CMK) per
deployment, one tenant data key (TDK) created per encryption operation (update
or insert).

The goal is to mitigate the risk [0] of a breach of the database (due to
misconfigured mongo, for example). This way, sensitive data cannot be
decrypted without a simultaneous and ongoing breach of KMS credentials. Even
if a hacker gets a DB dump, and somehow gets the KMS CMK and AWS credentials,
in order to decrypt sensitive data they still need to make a bunch of requests
to KMS, which should trigger CloudWatch alarms.

Envelope encryption has some obvious tradeoffs:

\- Lose ability to filter queries on plaintext value of encrypted fields. Can
be okay if all filtering operations are done client-side (e.g. in a CRM-like
application)

\- Speed tradeoff due to multiple round trips to KMS to decrypt data.
Alternative approach: instead of decrypting in afterFind, explicitly decrypt
data on field-by-field basis, in response to user action in client-side UI
(e.g. "click to decrypt...").

Resources:

\- [https://blog.koan.co/securing-customer-data-with-kms-and-
env...](https://blog.koan.co/securing-customer-data-with-kms-and-envelope-
encryption-in-node-js-b61983ddaa98)

\- [https://github.com/cjbischoff/kms-envelope-encryption-
aws](https://github.com/cjbischoff/kms-envelope-encryption-aws)

\-
[https://docs.aws.amazon.com/kms/latest/developerguide/concep...](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#enveloping)

[0] Keep in mind, this only mitigates _one risk_ ; that of access to the
database or a dump of it. Your security is still only as strong as your
application server. In the case I described, if the user can access a
sensitive field via parse-server, the user can decrypt that field. Security of
sensitive data depends just as much on the application-level permission system
as it does the database storage. For example, Equifax was breached because of
a flaw in the application level of Apache Struts. It didn't matter how they
stored sensitive fields in the database, because the user could just make
queries via Apache Struts and receive the decrypted data.

~~~
flashu
Gosh, thank You for such elaborative reply! I will definitely dive into the
idea of intercepting the query in before/after approach.

