In my database I store information which is encrypted and decrypted on the fly via a PHP-class.
Per application I use a private key appended with a user key to make sure the decryption only succeeds when a user tries to decrypt its own data.
The user 'key' is stored in the database; but the private key (application level) is stored as txt-file in the FS. Off course 'above' the web-root.
Considerations:
- If the database gets hacked: they end up with one part of the key, and encrypted data
- If PHP-stops or is corrupt: they end up with a single page with only include('../private/private.php')
in it.
- If NGINX fails: the connection is 'just' dropped.
The only scenario I can think of is the corruption of the system itself. But the server runs a firewall, is updated regularly, runs fail2ban and only the services needed are run. SSH logins only via key-access etc etc
I was wondering if this is the 'best' practice. Or if there is a better way to do this kind of encryption with above specifications? What would be the correct access-rights to the key-file?
At the moment the database and webserver are both on the same server facing the internet. Is it better to split them and create an internet facing server with only the webserver; and put the database server and key-file on a different server in a private network?
edit: the private key to encrypt the data is build up by two components:$key = $app_key . $user_key
The most secure method of storing your private keys is to use some form of cryptographic hardware storage device. While they can be expensive, tools like Hardware Storage Modules (HSM), Smart Cards, or USB tokens are great lines of defense against an attack.
A Private key for an end entity could be stored in a Trusted Platform Module (TPM) chip or a USB tamper-resistant security token. When hosting in the cloud, you should try to use the cloud-native key storage facilities provided by the vendor.
php // The unencrypted password to be hashed $unencrypted_password = "Cloudways@123"; // The hash of the password can be saved in the database $hash = password_hash($unencrypted_password, PASSWORD_DEFAULT); // Print the generated hash code echo "Generated hash code: ".
I was wondering if this is the 'best' practice. Or if there is a better way to do this kind of encryption with above specifications? What would be the correct access-rights to the key-file?
Hard to implement
To be perfectly secure you would need to generate a private-public key pair on an HSM (hardware security module) such as a smartcard or an HSM box. The generated private key is created inside the HSM and can never leave the HSM, it can only be used for decrypt / sign operations inside the HSM itself, however it can never be read off the HSM. In this case if someone hacks your server, or even get complete control over your server, they can never get hold of the private key stored inside HSM. Depending on number of decrypt / sign operations required on your server you would need a reasonably performing HSM to decrypt required data. Accomplishing this task in pure PHP is however a long way to go ( you could implement your own C++ extension or use inter-process communication with a process that is able interact with HSMs)
Easier to implement
It is important to harden your server and minimize the attack vector as much as you possibly can. This mainly includes assigning appropriate permissions to files and database. Have a look at this for some good security practices. To add my few cents you can use:
At the moment the database and webserver are both on the same server facing the internet. Is it better to split them and create an internet facing server with only the webserver; and put the database server and key-file on a different server in a private network?
Yes, separating the webserver from database server is definitely a good practice.
You can load the key into APC or something similar. This would require human input during boot (or perhaps kicked off from a more secured server). This would mean the key is never stored in any file on the server.
It's not perfect, but it's better than the more typical approach of using a local file.
q.v., Where should I store an encryption key for php?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With