As part of our efforts to reduce the friction to adopt secure authenticated secret-key encryption in the PHP community, our [Chief Development Officer](https://paragonie.com/blog/author/scott-arciszewski) has been helping Taylor Hornby develop the next version of [Defuse Security's PHP Encryption Library](https://github.com/defuse/php-encryption) (henceforth, referred to as, "Defuse Crypto"). After a year of research and development, we're happy to announce that version 2 is now available for use in your PHP projects. As always, if you're allowed to install PHP extensions, you should really consider using [PECL libsodium](https://github.com/jedisct1/libsodium-php) instead of a PHP-land cryptography library. We've contributed [documentation for libsodium in PHP](https://paragonie.com/book/pecl-libsodium). If you cannot (for whatever reason) install PHP extensions, **you're much better off using Defuse Crypto than attempting to write your own cryptography library**. ## Changes to `Crypto` at a Glance
Version 1.2.1Version 2.0.0Comment
Class Path Global namespace PSR-4 vendor namespace Everything is in \Defuse\Crypto now.
Encryption AES-128-CBC AES-256-CTR 256-bit keys offer $2^{128}$ post-quantum security
Message Integrity HMAC-SHA256 HMAC-SHA256 No change was necessary.
Key-Splitting Unsalted HKDF-HMAC-SHA256 Salted HKDF-HMAC-SHA256 Each message gets its own HKDF salt in addition to its own CTR nonce.
Version Tag? No Yes The header is included in the MAC
Output encoding Raw binary Hexadecimal We found that defaulting to raw binary was confusing to many users.
Encryption keys Strings Objects See below for details.
## New Features in Version 2.0.0 ### File Encryption The flagship feature of the next version of Defuse Crypto is the ability to encrypt large files (e.g. up to 2GB safely on a 32-bit OS) while using very low amounts of RAM. File encryption is facilitated by a new class, `\Defuse\Crypto\File`. This was originally designed by our CDO, and then improved greatly by Taylor Hornby and many open source contributors. We have benchmarked encrypting and decrypting a 173 MB file in under 4 seconds with less than 4 MB peak memory usage using `\Defuse\Crypto\File`. ## Changes and Improvements in Version 2.0.0 ### PSR-4 Namespace Between the last release (1.2.1) and Version 2, we have refactored the library to use the namespace `\Defuse\Crypto` in compliance with PSR-4. Previously, you could just use `Crypto::encrypt()` and `Crypto::decrypt()`. Now you have to options: Add a `use` statement or explicitly define the namespace. ### Version Tagging When you encrypt data in Defuse Crypto 2.0.0 and newer, a fixed header is prefixed to the encrypted payload. This header contains the version of the library used for encrypting the message. This allows the library maintainers to publish a newer version with stronger algorithms (should a weakness ever be found in AES-128-CBC, HMAC-SHA-256, etc.) without rendering previously encrypted messages inaccessible. A version tag for consists of 4 bytes: `D3 F5 XX XX`. the first two are a magic value specific to this library, the next two are the major and minor version. The header for version 2.0.x will be `D3 F5 02 00`. Should we need to update anything, version 2.1.x will use `D3 F5 02 01` and 3.0.x will use `D3 F5 03 00`. Patch releases (the third number) will not change the header. If you have previously encrypted data with an earlier version of this library, you can use `\Defuse\Crypto\Crypto::legacyDecrypt($your_ciphertext, $your_key)` to decrypt it. We recommend you decrypt all your old data and re-encrypt it with the new tagged format, as `legacyDecrypt()` will not exist in Version 3. This feature affects both the existing `\Defuse\Crypto\Crypto` class and the new `\Defuse\Crypto\File` class. ### Version 2 uses AES in Counter Mode, Exclusively Where the original version of Defuse Crypto used AES-128 in CBC (Cipher Block Chaining) mode, version 2 will use CTR (Counter) mode instead. There are many reasons contributing to this change: * CTR made far more sense for the design of the `File` API * Simplicity -- why use two different modes when only one is needed? * Public recommendations from [cryptographers](http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html) favor CTR over CBC * One more reason (see below) ### HKDF Now Uses Random Salts (Stored with Ciphertext) In addition to a random nonce for AES-128-CTR encryption, the library also generates and stores a random 256-bit salt for the HKDF key splitting feature. The reason for this change is subtle: If you encrypt $2^{64}$ messages with a random nonce, you have a 50% chance of generating at least one duplicate nonce. In probability, this is referred to as the [Birthday paradox](https://en.wikipedia.org/wiki/Birthday_problem). A duplicate nonce can degrade the security of your cryptosystem if you use the same key. Since version 1 of the library already introduced HKDF key splitting (to separate encryption keys from authentication keys), we added a 256-bit salt (which is also authenticated by the HMAC) for the HKDF calculation. * The situation before: Constant encryption and authentication keys, random IV. Collision after $2^{64}$ messages. * The situation now: Deterministic encryption and authentication keys from a random salt, random IV. Collision after $2^{192}$ messages. For the record 50% collision probability at $2^{64}$ is a rare event and $2^{192}$ is pretty close to "never going to happen before the heat death of the universe". This change affects both the existing `\Defuse\Crypto\Crypto` class and the new `\Defuse\Crypto\File` class.

Keys Are Objects, Not Strings

Before version 2, users needed to generate a random key and then figure out how to persist it. This also had the drawback that some users were tempted to use a human-readable password instead of a proper encryption key. Version 2 uses Key objects instead of strings: saveToAsciiSafeString(); To restore a key: saveToAsciiSafeString(); And then: unlock($password); // Now you can use $user_key directly without having to persist the password in memory ### Hexadecimal Encoding by Default Due to feedback from the developer community (whom were largely frustrated with MySQL altering their raw binary data and rendering it unusable), `\Defuse\Crypto\Crypto::encrypt()` has been changed to hex-encode output by default. If you want raw binary, simply pass `true` as the third argument; this usage is consistent with the `hash()` and `hash_hmac()` functions. This change affects both `Crypto::encrypt()` and `Crypto::decrypt()`. `Crypto::legacyDecrypt()` expects raw binary strings. ## How to Get Started with Defuse Crypto 2.0.0 If you're using Composer, you can simply run this command. composer require defuse/php-encryption:^2.0 For non-Composer-users: download the [PHP Archive and GPG signature bundled with the release](https://github.com/defuse/php-encryption/releases/tag/v2.0.0), verify the signature, and just `require` it. The [library's official documentation includes a tutorial](https://github.com/defuse/php-encryption/blob/master/docs/Tutorial.md) for getting started.