# Is this a good PHP encryption Strategy?

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.
• Is this a web application? Clients connect the webpage to read their message? Or you just send their phone? – kelalaka Sep 11 '18 at 19:38
• 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 – Dominic Kirby Sep 13 '18 at 1:58

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.

• 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. – Dominic Kirby Sep 13 '18 at 18:16
• So, you are saying that, the users trust you? – kelalaka Sep 13 '18 at 18:42
• 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). – Dominic Kirby Sep 14 '18 at 17:43
• In my mind, the only solution is using HSM. – kelalaka Sep 14 '18 at 20:30
• 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! – Dominic Kirby Sep 18 '18 at 18:22