For quite some time, Gyroscope has a pair of functions for encrypting and decrypting data. The encstr and decstr functions, defined in encdec.php, provide convenient ways to store information in a database in a non-plain text format.
Up till this point, these functions are not suitable for storing sensitive data because when a server is compromised, the encryption key is often taken with the data. Furthermore, data theft is often discovered too late; once the encrypted content is offloaded, the owner of the data no longer has control.
Gyroscope 17.7 extended the encstr and decstr functions with decentralized encryption keys, so that the following dreadful scenarios are handled:
By generating random keys remotely and not transmitting sensitive information between the application and key servers, the information obtained on either server is useless to an attacker.
In addition, the key server can erase the encryption keys, which is the equivalence of tossing a key into an acid ocean. The application server may also renew keys on a record basis, also known as a "key rotation".
Before we discuss more about the key server and how content is encrypted, let's look at the encryption routing from before:
$enckey='...'; //hard code some long keys
//not much safer because the key is predictable
$info='some sensitive data';
$enc=encstr($info,$reckey); //save $enc in the database
$dec=decstr($enc,$reckey); //getting back the sensitive data
The new method:
$reckey='patient-'.$patientid; //used to locate a remote entry
$info='some sensitive data';
$enc=encstr($info,$reckey,1); //1 for remote mode
The remote key server works as a dictionary. During encryption, a new random key is generated and stored remotely. The encryption key is then located by the same key, or a "record locator" during the remote decrypting process.
In addition, multiple encrypted strings can be decrypted with a single, batched request:
There are several implementations details that make this process secure.
The application server never sends the API key.
The key server assigns each Gyroscope project a unique alphanumeric "Client ID". Along with this ID is an API key - a shared secret between the application and key server. The API key, together with a few other request components, is used to compute a short-lived authentication token. In the extremely unlikely event of a TLS session between datacenters being diverted and decrypted, the intercept token cannot be used for long.
The application server never transmits the content to encrypt.
The key server is only used for issuing keys. The application server only sends the index of the sensitive record to the key server. Even this index itself can be hashed before transmitting. The key server has no knowledge of What the application server is encrypting.
The application server doesn't know how an encryption key is generated.
There are two kinds of keys being exchanged. One is an index, or a record locator. It is called a key in a key-value pairing context. The other key is the encryption key. Since the encryption key generating logic is kept away from the application server, the data stored on the server is safe even if the source code on the application server becomes accessible.
The random seeds on the key server are unpredictable.
An unpredictable encryption key requires a high level of randomness to generate. Obtaining true random numbers is actually very difficult because of computers' deterministic nature. The key server appends its pseudo-random seeds with additional random elements. The public key server, the one that responds to the "pubkey" account, for example, uses an OS vital digest as well as a random phrase from a library of books. The vitals of an OS include the CPU and RAM usage at the time, the distribution of file sizes in a particular folder (which is constantly changed as new web traffic and email requests come in). The following diagram shows the random tokens that were generated by a prototype key server:
Nothing stops the key server from adopting even crazier randomness from the physical world. After all, Cloudflare made a wall of lava lamps just for this.
The key server never stores, or cares about the API Secret.
The API secret is set by the application server; it is used to seal the envelopes that contain the generated key. The API secret is not stored on the key server, therefore, had the data on the key server get compromised, the stored keys cannot be decrypted. Here's a screenshot of some encrypted encryption keys:
And here's a look at the encrypted data on the application server:
Key rotation can take place more often and with ease.
A traditional key rotation can be a tedious process. With a remote key server, rotating a key for a specific record is as simple as re-encrypting the same record. The new key is generated remotely, and transparently to the application server. Fresher keys often means safer storage.
The key server can be distributed.
There is no single authoritative location for a key server. The Commercial Edition of Gyroscope has a key server that can be deployed anywhere, including private local networks. The key server can also be configured to only respond to specific IP ranges. This would prevent a stolen and relocated application server from leaking sensitive data.
In lb.php, set the values of the following keys:
The $encclientid and $encapikey values have to agree with the key server. The $encapisecret can be set to any value. However, once it is set, it should not be changed unless it's a full key rotation.
Although the key server is not part of the Community Edition of Gyroscope, there is a shared account "pubtest" that can be used for development and testing purposes. There is no guarantee that the encrypted data stays decryptable, as the remote encryption key might be replaced or removed.
The diagnostic page sysinfo.php now shows whether remote encryption is working correctly:
By default, the Google Authenticator codes are now stored with remote encryption keys. Even the Community Edition users can avoid key collision by setting the "GYROSCOPE_PROJECT" variable to a unique value in auth.php. For production use, however, a dedicated key server is highly recommended.