> If the words on this page are confusing, please read our [guide to cryptography terms and concepts](https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded) first.
**Cryptography is not magic.** Adding encryption to an application doesn't *automatically* make it secure against attackers (especially if you [aren't authenticating your ciphertext](https://paragonie.com/blog/2015/05/using-encryption-and-authentication-correctly)). But if you *do* need it to satisfy a business need, conventional wisdom states that [you almost certainly should not try to design your own cryptography](http://www.cryptofails.com/post/75204435608/write-crypto-code-dont-publish-it). Instead, you should use an existing cryptography library.
**Okay, great. So which PHP cryptography library should I use?**
That depends on your exact requirements. Let's look at some good choices. (We won't cover any terrible choices.)
## Secure PHP Cryptography Library Recommendations
What follows is a list of PHP cryptography libraries that we would ever feel confident deploying in a production environment. This list is prioritized based on three criteria:
1. How secure is the library if used correctly?
2. How hard is it to do something dangerous?
3. How easy is it for a non-cryptographer to use to its fullest?
Halite - Paragon Initiative Enterprises
We're not just recommending this one because we wrote it, it's our first suggestion because you get all the security of [using libsodium](https://paragonie.com/blog/2015/09/how-to-safely-implement-cryptography-in-any-application) with a simple and intuitive interface. **It's free software** and the source code is readily available.
**Benefits of Using Halite**:
* Mainline:
* Symmetric-key authenticated encryption
* Symmetric-key authentication (e.g. for API messages)
* Asymmetric-key authenticated encryption
* Asymmetric-key anonymous encryption
* Asymmetric-key digital signatures
* Whole-file cryptography (see: all mainline features)
* Encrypted cookies
* Password storage
* You don't have to know what a *nonce* is, and you don't need to particularly care about authenticated encryption. Halite does all of that for you.
We built [Halite](https://paragonie.com/project/halite) so PHP developers could get all the security benefits of [the libsodium extension](https://pecl.php.net/package/libsodium), but with a simpler interface. Check out the [Halite documentation](https://github.com/paragonie/halite/tree/master/doc) to see how easy it is to use. (Although the API is stable, the documentation is incomplete but it covers enough to get you started.)
The only downside is that you must be able to [install the libsodium PHP extension](https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium) to use Halite. For many projects, this is a no-go.
**Installation Guide:**
1. [Install the libsodium PHP extension](https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium).
2. `composer require paragonie/halite`
Obviously, if you don't like any of the design decisions we made with Halite, you can (read: **should**) consider [just using libsodium](https://paragonie.com/blog/2015/09/how-to-safely-implement-cryptography-in-any-application) directly.
**Benefits of Using Libsodium**:
* Symmetric-key authenticated encryption (also: AEAD)
* Symmetric-key authentication
* Asymmetric-key authenticated encryption
* Asymmetric-key anonymous encryption
* Asymmetric-key digital signatures
* Cryptographic hash functions
* Password storage
* A swiss army knife of cryptography primitives (e.g. Elliptic Curve Diffie-Hellman over Curve25519)
* The ability to wipe (zero-fill) memory in PHP
* [So much more](https://download.libsodium.org/doc/)
Hats off to [Frank Denis](https://00f.net) for maintaining one of the most reliable, cross-platform cryptography libraries in the world, and also to the team that wrote [NaCl](http://nacl.cr.yp.to) (which libsodium is forked from).
**Installation guide**:
See [the relevant documentation](https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium).
If you can't install PHP extensions from PECL (so no libsodium ever), this library should be your Plan B. In general, you should even prioritize it over whatever your framework provides, as our security team often finds vulnerabilities in the symmetric-key encryption features that PHP frameworks provide.
**Benefits of using Defuse Security's PHP Encryption Library**:
* Symmetric-key authenticated encryption
It solves a single problem that most people get wrong (and solves it *well*). Version 2 of the library (coming *soon*!) will also include whole-file encryption, but it's not out yet, so we can't give it credit for that just yet.
**Installation guide**:
composer require defuse/php-encryption
If you must implement symmetric-key encryption, use Defuse's library above. Defuse Security's library gives you *Authenticated Encryption*, whereas [phpseclib's AES implementation **does not authenticate ciphertexts**](http://phpseclib.sourceforge.net/crypt/examples.html), so if you use it, you will be vulnerable to **chosen-ciphertext attacks**. (Their interactive documentation also dangerously defaults to ECB mode, which is [the worst block cipher mode](https://filippo.io/the-ecb-penguin).)
Even though phpseclib exposes far too low-of-a-level an API for general purpose symmetric-key cryptography for us to recommend it to PHP developers that lack any cryptography background, they offer a better asymmetric-key cryptography interface than `ext/openssl`.
If you absolutely must implement asymmetric-key cryptography (public-key encryption, digital signatures) and you can't use libsodium for whatever reason, then you want to use phpseclib's implementation while strictly following [the cryptography right answers](http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html) given by Colin Percival.
Specifically:
* **RSA Encryption**: [RSA-OAEP](http://phpseclib.sourceforge.net/rsa/examples.html#encrypt,enc1), taking care to `$rsa->setMGFHash('sha256')` first
* **RSA Signatures**: [RSA-PSS](http://phpseclib.sourceforge.net/rsa/examples.html#sign,sign1), once again explicitly using MGF1+SHA256
If you happen to be a cryptography expert, you can ignore our warnings and use phpseclib for symmetric-key cryptography as well. But most programmers aren't, so please don't.
**Benefits of using PHPSecLib**:
* Symmetric-key authentication (via HMAC, which PHP offers too)
* Asymmetric-key anonymous encryption (RSA)
* Asymmetric-key digital signatures (RSA)
**Installation guide**:
composer require phpseclib/phpseclib
Update (2015-11-19): Easy RSA - Paragon Initiative Enterprises
After this blog post was published, we wrote [EasyRSA](https://github.com/paragonie/EasyRSA) as a drop-in implementation of our advice. EasyRSA uses phpseclib in an opinionated, secure-by-default manner.
#### EasyRSA Encryption Process
**Problem:** Encrypt an incredibly large string with RSA, even though RSA itself doesn't support encrypting large strings of data.
The naive solution is to break your input string into chunks then encrypt each one individually. Unfortunately, this is very similar to [the dreaded ECB mode](https://filippo.io/the-ecb-penguin). Also: It would be terribly slow. This is a bad idea.
**Our solution**:
1. Generate an ephemeral encryption key
2. Encrypt your message using [Defuse Security's PHP symmetric-key encryption library](https://github.com/defuse/php-encryption)
3. Encrypt the ephemeral key with the given RSA public key (using a mode that actually isn't vulnerable to padding oracles)
4. Base64-encode and concatenate both ciphertexts with a version tag prefix
5. Append a checksum (truncated SHA256 hash) of step 4 to make it easier to detect transmission / storage errors
To decrypt a message:
1. Verify the checksum and version tag
2. Decrypt the ephemeral key using the correct RSA private key
3. Use the decrypted key in step 2 to obtain the plaintext
EasyRSA only uses RSAES-OAEP + MGF1-SHA256 with e = 65537 for public-key encryption, which is not known to be vulnerable to any padding oracle attacks.
#### EasyRSA Signature Process
RSA signatures are comparatively straightforward: Calculate an RSA signature using RSASS-PSS + MGF1-SHA256 with e = 65537, then verify it configured to only accept those kind of signatures.
------
But seriously, if you want secure cryptography for your PHP project, try to find a way to use libsodium. We're pushing to [make libsodium a core extension in PHP 7.1](https://paragonie.com/blog/2015/09/state-cryptography-in-php), so hopefully this will be as easy as "update to the latest version of PHP" in the near future.
## About Our PHP Cryptography Library Recommendations
### What About Other Libraries?
If any library is not listed above, its absence can be explained by one of three possible reasons:
1. We have audited the library, and it wasn't secure enough for us to recommend it in good conscience. (Chances are, we've also notified the authors of any vulnerabilities we found so they can be fixed.)
2. It's an extremely narrow use case (e.g. [`Crypt_GPG`](https://pear.php.net/package/Crypt_GPG)) and, while secure, isn't relevant to the most common use cases for cryptography.
3. We are very busy and haven't had a chance to audit it yet. (We might not even know it exists.)
If you're interested in some of the libraries we've found to be vulnerable, check out our [security advisories](https://paragonie.com/security) page.
### What Should I Use to Encrypt Passwords in PHP?
Well, [you don't encrypt passwords, you hash them](https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded) with [an appropriate password-hashing algorithm](http://codahale.com/how-to-safely-store-a-password). Currently, the best password library to use is the one built into PHP: `password_hash()` and `password_verify()`. This is unlikely to change for 99% of programmers or businesses. It's just that good.
However, if you're storing passwords in a database that sits on a separate server from your web application, you can make password compromises less likely by encrypting the hashes (*not* encrypting the passwords themselves). In which case, check out [Halite's `Password` class](https://github.com/paragonie/halite/blob/master/doc/Classes/Password.md).
## Important Security Advice Disclaimer
Although we do employ some of the leading experts in secure PHP development (and we specialize in applied cryptography), without understanding your specific project requirements and threat model, they weren't in a position to guide you to the best solution to meet your ends when they wrote this.
So if you, for example, need asymmetric encryption and elect to use Defuse Security's symmetric encryption library instead, please don't say, "Paragon Initiative Enterprises told me to do it this way!"
If you want our security advice, specific to your project, please consider [hiring us for our security consulting services](https://paragonie.com/contact).
Or, in legalese: The information on this page is provided as-is and without warranty. Use it at your own risk.