Verified Commit d5fefe42 authored by mirabilos's avatar mirabilos Committed by mirabilos

php-defuse-php-encryption_2.2.0.orig.tar.gz

parents
*~
/test/unit/File/big-generated-file
/composer.lock
/vendor
defuse-crypto.phar
defuse-crypto.phar.sig
composer.phar
box.phar
phpunit.phar
phpunit.phar.asc
test/unit/File/tmp
<?php
$config = Symfony\CS\Config\Config::create()
->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
->fixers([
'blankline_after_open_tag',
'empty_return',
'extra_empty_lines',
'function_typehint_space',
'join_function',
'method_argument_default_value',
'multiline_array_trailing_comma',
'no_blank_lines_after_class_opening',
'no_empty_lines_after_phpdocs',
'phpdoc_indent',
'phpdoc_no_access',
'phpdoc_no_empty_return',
'phpdoc_no_package',
'phpdoc_params',
'phpdoc_scalar',
'phpdoc_separation',
'phpdoc_trim',
'phpdoc_type_to_var',
'phpdoc_types',
'phpdoc_var_without_name',
'remove_leading_slash_use',
'remove_lines_between_uses',
'short_bool_cast',
'single_quote',
'spaces_after_semicolon',
'spaces_before_semicolon',
'spaces_cast',
'standardize_not_equal',
'ternary_spaces',
'trim_array_spaces',
'unneeded_control_parentheses',
'unused_use',
'whitespacy_lines',
'align_double_arrow',
'concat_with_spaces',
'logical_not_operators_with_successor_space',
'multiline_spaces_before_semicolon',
'newline_after_open_tag',
'ordered_use',
'php_unit_construct',
'phpdoc_order',
'short_array_syntax',
]);
if (null === $input->getArgument('path')) {
$config
->finder(
Symfony\CS\Finder\DefaultFinder::create()
->in('src')
->in('test')
->exclude('vendor')
);
}
return $config;
The MIT License (MIT)
Copyright (c) 2016 Taylor Hornby <https://defuse.ca> and Paragon Initiative
Enterprises <https://paragonie.com>.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
php-encryption
===============
[![Build Status](https://travis-ci.org/defuse/php-encryption.svg?branch=master)](https://travis-ci.org/defuse/php-encryption)
[![codecov](https://codecov.io/gh/defuse/php-encryption/branch/master/graph/badge.svg)](https://codecov.io/gh/defuse/php-encryption)
[![Latest Stable Version](https://poser.pugx.org/defuse/php-encryption/v/stable)](https://packagist.org/packages/defuse/php-encryption)
[![Latest Unstable Version](https://poser.pugx.org/defuse/php-encryption/v/unstable)](https://packagist.org/packages/defuse/php-encryption)
[![License](https://poser.pugx.org/defuse/php-encryption/license)](https://packagist.org/packages/defuse/php-encryption)
[![Downloads](https://img.shields.io/packagist/dt/defuse/php-encryption.svg)](https://packagist.org/packages/defuse/php-encryption)
This is a library for encrypting data with a key or password in PHP. **It
requires PHP 5.6 or newer and OpenSSL 1.0.1 or newer.** The current version is
v2.2.0, which is expected to remain stable and supported by its authors with
security and bugfixes until at least January 1st, 2020.
The library is a joint effort between [Taylor Hornby](https://defuse.ca/) and
[Scott Arciszewski](https://paragonie.com/blog/author/scott-arcizewski) as well
as numerous open-source contributors.
What separates this library from other PHP encryption libraries is, firstly,
that it is secure. The authors used to encounter insecure PHP encryption code on
a daily basis, so they created this library to bring more security to the
ecosystem. Secondly, this library is "difficult to misuse." Like
[libsodium](https://github.com/jedisct1/libsodium), its API is designed to be
easy to use in a secure way and hard to use in an insecure way.
Dependencies
------------
This library requires no special dependencies except for PHP 5.6 or newer with
the OpenSSL extensions (version 1.0.1 or later) enabled (this is the default).
It uses [random\_compat](https://github.com/paragonie/random_compat), which is
bundled in with this library so that your users will not need to follow any
special installation steps.
Getting Started
----------------
Start with the [**Tutorial**](docs/Tutorial.md). You can find instructions for
obtaining this library's code securely in the [Installing and
Verifying](docs/InstallingAndVerifying.md) documentation.
After you've read the tutorial and got the code, refer to the formal
documentation for each of the classes this library provides:
- [Crypto](docs/classes/Crypto.md)
- [File](docs/classes/File.md)
- [Key](docs/classes/Key.md)
- [KeyProtectedByPassword](docs/classes/KeyProtectedByPassword.md)
If you encounter difficulties, see the [FAQ](docs/FAQ.md) answers. The fixes to
the most commonly-reported problems are explained there.
If you're a cryptographer and want to understand the nitty-gritty details of how
this library works, look at the [Cryptography Details](docs/CryptoDetails.md)
documentation.
If you're interested in contributing to this library, see the [Internal
Developer Documentation](docs/InternalDeveloperDocs.md).
Other Language Support
----------------------
This library is intended for server-side PHP software that needs to encrypt data at rest.
If you are building software that needs to encrypt client-side, or building a system that
requires cross-platform encryption/decryption support, we strongly recommend using
[libsodium](https://download.libsodium.org/doc/bindings_for_other_languages) instead.
Examples
---------
If the documentation is not enough for you to understand how to use this
library, then you can look at an example project that uses this library:
- [encutil](https://github.com/defuse/encutil)
- [fileencrypt](https://github.com/tsusanka/fileencrypt)
Security Audit Status
---------------------
This code has not been subjected to a formal, paid, security audit. However, it
has received lots of review from members of the PHP security community, and the
authors are experienced with cryptography. In all likelihood, you are safer
using this library than almost any other encryption library for PHP.
If you use this library as a part of your business and would like to help fund
a formal audit, please [contact Taylor Hornby](https://defuse.ca/contact.htm).
Public Keys
------------
The GnuPG public key used to sign releases is available in
[dist/signingkey.asc](https://github.com/defuse/php-encryption/raw/master/dist/signingkey.asc). Its fingerprint is:
```
2FA6 1D8D 99B9 2658 6BAC 3D53 385E E055 A129 1538
```
You can verify it against Taylor Hornby's [contact
page](https://defuse.ca/contact.htm) and
[twitter](https://twitter.com/DefuseSec/status/723741424253059074).
#!/usr/bin/env php
<?php
use Defuse\Crypto\Key;
foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
if (file_exists($file)) {
require $file;
break;
}
}
$key = Key::createNewRandomKey();
echo $key->saveToAsciiSafeString(), "\n";
{
"name": "defuse/php-encryption",
"description": "Secure PHP Encryption Library",
"license": "MIT",
"keywords": ["security", "encryption", "AES", "openssl", "cipher", "cryptography", "symmetric key cryptography", "crypto", "encrypt", "authenticated encryption"],
"authors": [
{
"name": "Taylor Hornby",
"email": "taylor@defuse.ca",
"homepage": "https://defuse.ca/"
},
{
"name": "Scott Arciszewski",
"email": "info@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"autoload": {
"psr-4": {
"Defuse\\Crypto\\": "src"
}
},
"require": {
"paragonie/random_compat": "~2.0",
"ext-openssl": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4|^5",
"nikic/php-parser": "^2.0|^3.0|^4.0"
},
"bin": [
"bin/generate-defuse-key"
]
}
# This builds defuse-crypto.phar. To run this Makefile, `box` and `composer`
# must be installed and in your $PATH. Run it from inside the dist/ directory.
box := $(shell which box)
composer := "composer"
.PHONY: all
all: build-phar
.PHONY: sign-phar
sign-phar:
gpg -u 7B4B2D98 --armor --output defuse-crypto.phar.sig --detach-sig defuse-crypto.phar
# ensure we run in clean tree. export git tree and run there.
.PHONY: build-phar
build-phar:
@echo "Creating .phar from revision $(shell git rev-parse HEAD)."
rm -rf worktree
install -d worktree
(cd $(CURDIR)/..; git archive HEAD) | tar -x -C worktree
$(MAKE) -f $(CURDIR)/Makefile -C worktree defuse-crypto.phar
mv worktree/*.phar .
rm -rf worktree
.PHONY: clean
clean:
rm -vf defuse-crypto.phar defuse-crypto.phar.sig
# Inside workdir/:
defuse-crypto.phar: dist/box.json composer.lock
cp dist/box.json .
php -d phar.readonly=0 $(box) build -c box.json -v
composer.lock:
$(composer) install --no-dev
{
"chmod": "0755",
"finder": [
{
"in": "src",
"name": "*.php"
},
{
"in": "vendor/composer",
"name": "*.php"
},
{
"in": "vendor/paragonie",
"name": "*.php",
"exclude": "other"
}
],
"compactors": [
"Herrera\\Box\\Compactor\\Php"
],
"main": "vendor/autoload.php",
"output": "defuse-crypto.phar",
"shebang": false,
"stub": true
}
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
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
IEgAL/CYqrk38w==
=lmD7
-----END PGP PUBLIC KEY BLOCK-----
Cryptography Details
=====================
Here is a high-level description of how this library works. Any discrepancy
between this documentation and the actual implementation will be considered
a security bug.
Let's start with the following definitions:
- HKDF-SHA256(*k*, *n*, *info*, *s*) is the key derivation function specified in
RFC 5869 (using the SHA256 hash function). The parameters are:
- *k*: The initial keying material.
- *n*: The number of output bytes.
- *info*: The info string.
- *s*: The salt.
- AES-256-CTR(*m*, *k*, *iv*) is AES-256 encryption in CTR mode. The parameters
are:
- *m*: An arbitrary-length (possibly zero-length) message.
- *k*: A 32-byte key.
- *iv*: A 16-byte initialization vector (nonce).
- PBKDF2-SHA256(*p*, *s*, *i*, *n*) is the password-based key derivation
function defined in RFC 2898 (using the SHA256 hash function). The parameters
are:
- *p*: The password string.
- *s*: The salt string.
- *i*: The iteration count.
- *n*: The output length in bytes.
- VERSION is the string `"\xDE\xF5\x02\x00"`.
- AUTHINFO is the string `"DefusePHP|V2|KeyForAuthentication"`.
- ENCRINFO is the string `"DefusePHP|V2|KeyForEncryption"`.
To encrypt a message *m* using a 32-byte key *k*, the following steps are taken:
1. Generate a random 32-byte string *salt*.
2. Derive the 32-byte authentication key *akey* = HKDF-SHA256(*k*, 32, AUTHINFO, *salt*).
3. Derive the 32-byte encryption key *ekey* = HKDF-SHA256(*k*, 32, ENCRINFO, *salt*).
4. Generate a random 16-byte initialization vector *iv*.
5. Compute *c* = AES-256-CTR(*m*, *ekey*, *iv*).
6. Combine *ctxt* = VERSION || *salt* || *iv* || *c*.
7. Compute *h* = HMAC-SHA256(*ctxt*, *akey*).
8. Output *ctxt* || *h*.
Decryption is roughly the reverse process (see the code for details, since the
security of the decryption routine is highly implementation-dependent).
For encryption using a password *p*, steps 1-3 above are replaced by:
1. Generate a random 32-byte string *salt*.
2. Compute *k* = PBKDF2-SHA256(SHA256(*p*), *salt*, 100000, 32).
3. Derive the 32-byte authentication key *akey* = HKDF-SHA256(*k*, 32, AUTHINFO, *salt*)
4. Derive the 32-byte encryption key *ekey* = HKDF-SHA256(*k*, 32, ENCRINFO, *salt*)
The remainder of the process is the same. Notice the reuse of the same *salt*
for PBKDF2-SHA256 and HKDF-SHA256. The prehashing of the password in step 2 is
done to prevent a [DoS attack using long
passwords](https://github.com/defuse/php-encryption/issues/230).
For `KeyProtectedByPassword`, the serialized key is encrypted according to the
password encryption defined above. However, the actual password used for
encryption is the SHA256 hash of the password the user provided. This is done in
order to provide domain separation between the message encryption in the user's
application and the internal key encryption done by this library. It fixes
a [key replacement chosen-protocol
attack](https://github.com/defuse/php-encryption/issues/240).
Frequently Asked Questions
===========================
How do I use this library to encrypt passwords?
------------------------------------------------
Passwords should not be encrypted, they should be hashed with a *slow* password
hashing function that's designed to slow down password guessing attacks. See
[How to Safely Store Your Users' Passwords in
2016](https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016).
How do I give it the same key every time instead of a new random key?
----------------------------------------------------------------------
A `Key` object can be saved to a string by calling its `saveToAsciiSafeString()`
method. You will have to save that string somewhere safe, and then load it back
into a `Key` object using `Key`'s `loadFromAsciiSafeString` static method.
Where you store the string depends on your application. For example if you are
using `KeyProtectedByPassword` to encrypt files with a user's login password,
then you should not store the `Key` at all. If you are protecting sensitive data
on a server that may be compromised, then you should store it in a hardware
security module. When in doubt, consult a security expert.
Why is an EnvironmentIsBrokenException getting thrown?
-------------------------------------------------------
Either you've encountered a bug in this library, or your system doesn't support
the use of this library. For example, if your system does not have a secure
random number generator, this library will refuse to run, by throwing that
exception, instead of falling back to an insecure random number generator.
Why am I getting a BadFormatException when loading a Key from a string?
------------------------------------------------------------------------
If you're getting this exception, then the string you're giving to
`loadFromAsciiSafeString()` is *not* the same as the string you got from
`saveToAsciiSafeString()`. Perhaps your database column isn't wide enough and
it's truncating the string as you insert it?
Does encrypting hide the length of the plaintext?
--------------------------------------------------
Encryption does not, and is not intended to, hide the length of the data being
encrypted. For example, it is not safe to encrypt a field in which only a small
number of different-length values are possible (e.g. "male" or "female") since
it would be possible to tell what the plaintext is by looking at the length of
the ciphertext. In order to do this safely, it is your responsibility to, before
encrypting, pad the data out to the length of the longest string that will ever
be encrypted. This way, all plaintexts are the same length, and no information
about the plaintext can be gleaned from the length of the ciphertext.
Getting The Code
=================
There are two ways to use this library in your applications. You can either:
1. Use [Composer](https://getcomposer.org/), or
2. `require_once` a single `.phar` file in your application.
If you are not using either option (for example, because you're using Git submodules), you may need to write your own autoloader ([example](https://gist.github.com/paragonie-scott/949daee819bb7f19c50e5e103170b400)).
Option 1: Using Composer
-------------------------
Run this inside the directory of your composer-enabled project:
```sh
composer require defuse/php-encryption
```
Unfortunately, composer doesn't provide a way for you to verify that the code
you're getting was signed by this library's authors. If you want a more secure
option, use the `.phar` method described below.
Option 2: Including a PHAR
----------------------------
The `.phar` option lets you include this library into your project simply by
calling `require_once` on a single file. Download `defuse-crypto.phar` and
`defuse-crypto.phar.sig` from this project's
[releases](https://github.com/defuse/php-encryption/releases) page.
You should verify the integrity of the `.phar`. The `defuse-crypto.phar.sig`
contains the signature of `defuse-crypto.phar`. It is signed with Taylor
Hornby's PGP key. You can find Taylor's public key in `dist/signingkey.asc`. You
can verify the public key's fingerprint against the Taylor Hornby's [contact
page](https://defuse.ca/contact.htm) and
[twitter](https://twitter.com/DefuseSec/status/723741424253059074).
Once you have verified the signature, it is safe to use the `.phar`. Place it
somewhere in your file system, e.g. `/var/www/lib/defuse-crypto.phar`, and then
pass that path to `require_once`.
```php
<?php
require_once('/var/www/lib/defuse-crypto.phar');
// ... the Crypto, File, Key, and KeyProtectedByPassword classes are now
// available ...
// ...
```
Information for the Developers of php-encryption
=================================================
Status
-------
This library is currently frozen under a long-term support release. We do not
plan to add any new features. We will maintain the library by fixing any bugs
that are reported, or security vulnerabilities that are found.
Development Environment
------------------------
Development is done on Linux. To run the tests, you will need to have the
following tools installed:
- `php` (with OpenSSL enabled, if you're compiling from source).
- `gpg`
- `composer`
Running the Tests
------------------
First do `composer install` and then you can run the tests by running
`./test.sh`. This will download a PHPUnit PHAR, verify its cryptographic
signatures, and then use it to run the tests in `test/unit`.
Getting and Using Psalm
-----------------------
[Psalm](https://github.com/vimeo/psalm) is a static analysis suite for PHP projects.
We use Psalm to ensure type safety throughout our library.
To install Psalm, you just need to run one command:
composer require --dev "vimeo/psalm:dev-master"
To verify that your code changes are still strictly type-safe, run the following
command:
vendor/bin/psalm
Reporting Bugs
---------------
Please report bugs, even critical security vulnerabilities, by opening an issue
on GitHub. We recommend disclosing security vulnerabilities found in this
library *publicly* as soon as possible.
Philosophy
-----------
This library is developed around several core values:
- Rule #1: Security is prioritized over everything else.
> Whenever there is a conflict between security and some other property,
> security will be favored. For example, the library has runtime tests,
> which make it slower, but will hopefully stop it from encrypting stuff
> if the platform it's running on is broken.
- Rule #2: It should be difficult to misuse the library.
> We assume the developers using this library have no experience with
> cryptography. We only assume that they know that the "key" is something
> you need to encrypt and decrypt the messages, and that it must be kept
> secret. Whenever possible, the library should refuse to encrypt or decrypt
> messages when it is not being used correctly.
- Rule #3: The library aims only to be compatible with itself.
> Other PHP encryption libraries try to support every possible type of
> encryption, even the insecure ones (e.g. ECB mode). Because there are so
> many options, inexperienced developers must decide whether to use "CBC
> mode" or "ECB mode" when both are meaningless terms to them. This
> inevitably leads to vulnerabilities.
> This library will only support one secure mode. A developer using this
> library will call "encrypt" and "decrypt" methods without worrying about
> how they are implemented.
- Rule #4: The library should require no special installation.
> Some PHP encryption libraries, like libsodium-php, are not straightforward
> to install and cannot packaged with "just download and extract"
> applications. This library will always be just a handful of PHP files that
> you can copy to your source tree and require().
Publishing Releases
--------------------
To make a release, you will need to install [composer](https://getcomposer.org/)
and [box](https://github.com/box-project/box2) on your system. They will need to
be available in your `$PATH` so that running the commands `composer` and `box`
in your terminal run them, respectively. You will also need the private key for
signing (ID: 7B4B2D98) available.
Once you have those tools installed and the key available follow these steps:
**Remember to set the version number in `composer.json`!**
Make a fresh clone of the repository:
```
git clone <url>
```
Check out the branch you want to release:
```
git checkout <branchname>
```
Check that the version number in composer.json is correct:
```
cat composer.json
```
Check that the version number and support lifetime in README.md are correct:
```
cat README.md
```
Run the tests:
```
composer install
./test.sh
```
Generate the `.phar`:
```
cd dist
make build-phar
```
Test the `.phar`:
```
cd ../
./test.sh dist/defuse-crypto.phar
```
Sign the `.phar`:
```
cd dist
make sign-phar
```
Tag the release:
```
git -c user.signingkey=7B4B2D98 tag -s "<TAG NAME>" -m "<TAG MESSAGE>"
```
`<TAG NAME>` should be in the format `v2.0.0` and `<TAG MESSAGE>` should look
like "Release of v2.0.0."
Push the tag to github, then use the
[releases](https://github.com/defuse/php-encryption/releases) page to draft
a new release for that tag. Upload the `.phar` and the `.phar.sig` file to be
included as part of that release.
This diff is collapsed.
Upgrading From Version 1.2
===========================
With version 2.0.0 of this library came major changes to the ciphertext format,
algorithms used for encryption, and API.
In version 1.2, keys were represented by 16-byte string variables. In version
2.0.0, keys are represented by objects, instances of the `Key` class. This
change was made in order to make it harder to misuse the API. For example, in
version 1.2, you could pass in *any* 16-byte string, but in version 2.0.0 you
need a `Key` object, which you can only get if you're "doing the right thing."
This means that for all of your old version 1.2 keys, you'll have to:
1. Generate a new version 2.0.0 key.
2. For all of the ciphertexts encrypted under the old key:
1. Decrypt the ciphertext using the old version 1.2 key.
2. Re-encrypt it using the new version 2.0.0 key.
Use the special `Crypto::legacyDecrypt()` method to decrypt the old ciphertexts
using the old key and then re-encrypt them using `Crypto::encrypt()` with the
new key. Your code will look something like the following. To avoid data loss,
securely back up your keys and data before running your upgrade code.
```php
<?php
// ...
$legacy_ciphertext = // ... get the ciphertext you want to upgrade ...
$legacy_key = // ... get the key to decrypt this ciphertext ...
// Generate the new key that we'll re-encrypt the ciphertext with.
$new_key = Key::createNewRandomKey();
// ... save it somewhere ...
// Decrypt it.
try {
$plaintext = Crypto::legacyDecrypt($legacy_ciphertext, $legacy_key);
} catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex)
{
// ... TODO: handle this case appropriately ...
}
// Re-encrypt it.
$new_ciphertext = Crypto::encrypt($plaintext, $new_key);
// ... replace the old $legacy_ciphertext with the new $new_ciphertext