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.
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.