I need to store a user's sensitive input on a website (like SSN) into a database. This data cannot be a one-way hash. The data, once input into db, will never be sent again to a website or anyone untrusted, but may be sent via the server to another trusted API so I need to be able to read it.

Let's assume that we have proper access controls, keys are properly stored/managed, and all information is securely transmitted through HTTPS.

From what I have read online, the method that seems to make the most sense is using a public/private asymmetric key encryption. So:

  1. Generate a public/private key
  2. Give public key to client
  3. Encrypt data with public key on client and send to server
  4. Store encrypted data into DB
  5. Decode with private key when needed

Some questions:

  • Am I missing any steps here or misunderstanding anything?
  • Do I need to generate a new public key for each user on my website? Or is it okay to use the same public key every time any user is sending me an SSN?
  • Is it okay to store the publicly encrypted data directly on the db? Or is there something else I should do before storing it?



Using PKI (Public Key Infrastructure) for this doesn't make much sense if your users are actual users of your website / service. HTTPS is already doing transport layer encryption for you.

What you should do is data tokenization + encryption + compartmentalization.

A possible solution would be to setup a dedicated database and server that is separate from the rest of your application ecosystem, and use data-at-rest encryption for your database. In addition to this you can also use application-layer encryption to be extra-safe. (All this done using AES).

This database would be solely responsible for storing this PII (SSN's in your case) and therefore would associate every SSN with a random UUID that can be used in your "main application database" in liue of the actual encrypted data. This random UUID is essentially your foreign key to the sensitive data stored in the secure encrypted database.

This lets you put in place stricter ACL's and permission policies governing access to the encrypted database. For reading and writing you can have separate access policies, having separate access keys for reading and writing.

  • 1
    so you are saying that there's no need for some sort of public key encryption since HTTPS is already handling this? So it would be okay to send the SSN over https directly to my server? – wlingke Dec 13 '16 at 0:25
  • Yes, as long as the SSN is transmitted over HTTPS than you are doing your due diligence in terms of transport security. (Obviously making sure you have a valid certificate signed by a trusted CA). In terms of storing the data, you need to make sure you are encrypting it and compartmentalizing it properly. That is the difficult part. – Alex Urcioli Dec 13 '16 at 6:39
  • Are you certain you actually need to collect this information? I would avoid collecting information like this at all costs. Can it be replaced with a a pseudo random identifier? Last 4 of social? – Andrew Alaniz Dec 13 '16 at 17:37

You don't need public key cryptography for this. Standard AES should be fine.

Get an HSM (Yubico makes a reasonably inexpensive one). This does the encryption and decryption for you. The key never leaves the device.

You would do the encryption/decryption on the application server

  • so you are saying I can just send the PII directly over https to my server. Then application server encrypts and stores on an HSM? – wlingke Dec 13 '16 at 0:26
  • @wlingke the application encrypts and decrypts on the HSM but stores in the database – Neil McGuigan Dec 13 '16 at 1:07

If what you are describing is a project involving actual people's private information, I recommend going for professional/commercial DB encryption solutions instead of attempting to implement encryption on your own.

You know the common saying that you shouldn't roll your own. To paraphrase a comment I once read somewhere, "Unless you've written a PhD on the subject, you're not qualified to write your own crypto algorithm."

But even if you use a proved algorithm such as RSA, AES, etc there are a lot of things that can go wrong during implementation.

This is especially true when it comes to database encryption.

You want to make sure you are using the most secure algorithm but also that you're implementing it in a way that does not compromise your database performance.

You need to know that you are using proper block cipher mode or applying the Initial vector properly. You need to know that your encryption does not sabotage your existing data models, relationships or formats. Go for solutions with Format Preserving Encryption technology.

You need to make sure that your implementation takes good care of the encryption key life cycle and apply proper audits on each one of the encrypted column.

I'm telling you as someone who has been there. Unless it's just a pet project, go for proven and tested solutions on that market that fit your particular needs. You don't tell us much about which DBMS you are using (it may matter alot) but what I figure is that it's a relational DB. Since you won't need to encrypt everything in the DB, I would recommend going for column-based encryption. That way you will be able to set specific encryption and access control policies/keys per each one of the column. It may also boost the overall post-encryption performance.

If you are using Open Source RDBMS this may be a good solution for your case. For commercial RDBMS, vendors usually have corresponding column-based encryption or you may want to check out this or this or this.

Hope the answer helps.

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.