2
$\begingroup$

I'm writing a multi-tenant application that interacts with a couple of different APIs on behalf of each customer. Obviously, we need to store private keys for these various different APIs in the database so that we can connect to them. Goes without saying, I need to encrypt those.

I wanted to use a separate encryption key for each tenant on the system (I'm using openssl_encrypt with AES-256-CBC). To accomplish this, I have a separate "crypto" database. The tenant_keys table contains the following columns:

  • A tenant_hash, which is a has of a random value stored in the tenant's settings table, used for lookup
  • A tenant_key, which is the tenant's unique encryption key.
  • A key_timestamp that I'll use in the future to periodically rekey tenants

The obvious weakness is that if the database were stolen, the attacker would have all of the keys. To combat this, I've generated a "master key" that is stored as a text file on the server. This master key is then used to encrypt all of the various tenant keys. So, when a session is first initiated and the tenant is looked up, the tenant's key is decrypted and stored in the session. So, here are my questions:

  • Is there a better way to secure each tenant key (perhaps some sort of key server, but building an entire CA hierarchy and such seems like overkill vs protecting the master_key file with good chmod settings)?
  • Is there a safer way to store the tenant's key ephemerally without needing to do a round of decryption (costs CPU time) each time we need to use it, besides in the PHP session? The PHP sessions will ultimately be stored in some sort of shared storage (probably redis) as the environment will be clustered.
$\endgroup$
2
  • $\begingroup$ Is this a web application? Clients connect the webpage to read their message? Or you just send their phone? $\endgroup$
    – kelalaka
    Commented Sep 11, 2018 at 19:38
  • $\begingroup$ It's a web application. It's going to be a billing automation tool that ties in with authorize.net and a psa software. Really all I'm encrypting are API private keys in the database. EDIT: it will not store payment data, I'll be using CIM for that $\endgroup$ Commented Sep 13, 2018 at 1:58

1 Answer 1

1
$\begingroup$

Protection Against Rainbow tables

First of all, design a log-in system so that users cannot set bad passwords and have protection against rainbow tables. One nice solution is using salt as in bcrypt.

Protection of Public Keys

Generate public-private pair for each user. Then, encrypt users private keys with their passwords and prefer Password Key Derivation Functions PKDF, so that you can prevent the guess and brute-force attacks on the user's passwords. You can use their password to encrypt and decrypt the key-encryption key.

Session Keys

When you want to send a message to a user, generate a session key and encrypt the message with AES crypto algorithm with an appropriate scheme, CBC, CTR or GCM, and secure the session key by the user public key with appropriate padding scheme.

Later on, when a user log-in the system, you can use their passwords to decrypt their private key and open the messages, if any, by extracting the session keys for each message. Hope this clear.

$\endgroup$
6
  • $\begingroup$ The issue is that this is an automation platform. So it needs to access the encrypted API keys on its own to pull invoices from the CRM and charge them with Authorize. $\endgroup$ Commented Sep 13, 2018 at 18:16
  • $\begingroup$ So, you are saying that, the users trust you? $\endgroup$
    – kelalaka
    Commented Sep 13, 2018 at 18:42
  • $\begingroup$ Yes, the users trust me. We're being given their private API keys in order to do work on their behalf. The vector we need to protect from is potential theft of the database (while extremely unlikely, if we ever release some bug by mistake we'd like to know that the keys are somewhat protected). $\endgroup$ Commented Sep 14, 2018 at 17:43
  • $\begingroup$ In my mind, the only solution is using HSM. $\endgroup$
    – kelalaka
    Commented Sep 14, 2018 at 20:30
  • $\begingroup$ That's not a bad way to think about it at all. I plan on running this in AWS - I'll look into their crypto offerings to manage this. Thanks! $\endgroup$ Commented Sep 18, 2018 at 18:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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