TCrypto is a simple and flexible PHP 5.3+ in-memory key-value storage library. By default, a cookie will be used as a storage backend.
TCrypto has been designed from the ground up with security in mind. Safe algorithms and modes. Automatic and safe initialization vector creation. Encryption and authentication key creation (Keytool) using strong randomness. Key rotation (versioned keys).
TCrypto can be used as a scalable "session handler". Especially scalable, if cookies are used as a storage backend. This is a bit like Ruby on Rails sessions.
There's an article outlining basic TCrypto usage at websec.io: TCrypto: Encrypted data storage for PHP applications
This is a preview release (although considered stable). Keyfile encryption will be available in version 1.0.0. Otherwise no other changes are planned between current dev-master and 1.0.0.
Important security note about data compression:
Prior to August 6 2013, TCrypto allowed to use data compression when the data was also being encrypted. This may lead to disclosure of the (confidential) plain text. All TCrypto users are encouraged to update to the current dev-master. Especially if CompressPlugin() was used with data encryption.
TCrypto is placed in the public domain.
TCrypto requires PHP version 5.3 or greater. To use encryption, either Mcrypt or OpenSSL extension must be available. If OpenSSL is used for encryption, PHP 5.3.3 or greater is required. Optional compression plugin requires zlib.
TCrypto supports installation using Composer, but make sure you use at least Composer version 1.0.0-beta1 to install TCrypto (Composer was vulnerable to MITM attacks before 1.0.0-beta1):
Backward incompatible changes
04 Dec 2015 String() StorageHandler was renamed to PlainString().
TCrypto Keymanager and Keytool
Keytool is a small command-line application, which is used to create encryption and authentication keys. Keytool can also be used to remove inactive keys.
Before you start using TCrypto, run Keytool and create your first set of keys:
$ cd /path/to/TCrypto/bin $ php keytool
Make sure the right keyfile is selected (if necessary, change keyfile) and select option 1 "Add new keys".
To remove inactive keys, run Keytool and select option 2 "Remove inactive keys". You should always remove inactive keys before you add new keys. This is because inactive keys are determined comparing the (current) primary key timestamp and key lifetime (keys that can not be active are removed).
There are a few Keytool settings you can tweak. File
- 'keyfile_permissions': the default filesystem permissions for the keyfile
- 'bytes_in_key_name': key name length
- 'key_max_lifetime': this should be the same as $_macMaxLifetime in TCrypto
- 'keyfile_location': the default keyfile location
If you remove or comment out 'keyfile_permissions' setting, chmod() won't be run at all for the keyfile.
Keytool stores keys as a plain PHP array. The key format is as follows:
<?php array ( 'tcrypto_key_data' => array ( 'keys' => array ( 'index_xxx' => array ( 'encryption' => 'key_xxx', 'authentication' => 'key_xxx', 'time' => xxx, ), ), 'meta_data' => array ( 'primary_index' => 'index_xxx', 'last_key_creation_time' => xxx, ), ), );
'index_xxx' means a unique array index. Keytool will (by default) use 3 bytes of entropy in a key name (hexadecimal format). 3 bytes can produce about 4096 distinct keys without collisions. Given that you should probably have no more than a few keys in your keyfile, 3 bytes of entropy in a key name will be easily enough.
'meta_data' is used to identify the current primary key index.
There can be multiple keys in the 'keys' array. However, you should remove constantly inactive keys (to avoid filling your key file with "junk"). It is a good idea to always remove inactive keys before you add new keys.
<?php require '/path/to/library/TCrypto/Loader.php'; $loader = new TCrypto\Loader(); $loader->register();
About symmetric encryption
Currently there are four choices for an encryption provider:
OpenSslAes128Cbc/McryptAes128Cbc and OpenSslAes256Cbc/McryptAes256Cbc both implement AES in CBC mode using a random initializing vector. Only the key size differs between them. 128-bit key size should be unbreakable with foreseeable technology. But on the other hand, 256-bit keys provides more margin of security (against side channels etc.). Encrypting with 128-bit keys should be somewhat faster than encrypting with 256-bit keys. However, in a typical web application usage scenario, this speed difference is probably insignificant.
If you feel paranoid (the bigger, the better fetish), use McryptAes256Cbc. Otherwise use McryptAes128Cbc.
TCrypto derives encryption keys from variable data (timestamps, initializing vector, key seeds and user supplied extra entropy sources). This guarantees that a fresh and random key will be used for each encryption operation. The key setup combined with (truncated) SHA512 hashing ensures (currently known) related-key attacks does not apply against AES-256 (McryptAes256Cbc).
If your system supports OpenSSL, use OpenSSL based encryption (OpenSslAes128Cbc or OpenSslAes256Cbc).
TCrypto comes with a simple "plugin system". Plugins are run in two separate places.
Before saving the data to a storage.
After extracting the data from a storage (plugins are run in reverse order).
It is important to note that you can not use data compression plugins if you are using data encryption.
If you configure TCrypto to use data compression at the same time data is being encrypted, the PluginContainer will automatically skip data compression plugins.
This is important because compressing confidential (encrypted) data may leak information about the plain text.
This creates the required serialize/unserialize plugin:
<?php // PluginContainer() automatically attaches DefaultPlugin(), which handles // serializing and unserializing. $plugins = new TCrypto\PluginContainer();
You can also attach more plugins:
<?php // NOTE: CompressPlugin will not be run if data encryption is being used. // This is because data compression leaks information about the plain text. $plugins->attachPlugin(new TCrypto\Plugin\CompressPlugin());
Now the data will be first serialized and then compressed (when saving). When extracting the data from a storage, the data will be first uncompressed and then unserialized.
NOTE: $plugins->attach() is not supported anymore. Use $plugins->attachPlugin() instead of $plugins->attach().
TCrypto Keytool will write all encryption/authentication keys to a filesystem. Make sure this keyfile can not be read by anyone else. It is probably a good idea to use chmod 0600 setting for the keyfile (depending on your server settings).
Cookies as a storage backend
By default, TCrypto uses browser cookies as a "permanent" storage backend. If you do not use encryption, anyone who you send the data can read (but not modify) it. It is up to you to decide does the data need to be encrypted.
It should be pointed out that TCrypto does not address replay of old cookies. Legitimate client can send previous (old) cookies within the "max_lifetime" period.
HTTPS connection is another important concern about browser cookies. If there is no "secure connection", the data may be captured (and replayed) by whoever is eavesdropping on the line.
When extracting the data from a storage, an HMAC value will be checked BEFORE the plugins are run. This could potentially lead to bugs or security issues. If you use any extra plugins, make sure they operate correctly.
Issues or questions?
Mail me at [email protected] or use GitHub.