Skip to content

Commit

Permalink
13.1.0 (#31)
Browse files Browse the repository at this point in the history
* no message

* no message

* no message

* no message

* no message

* no message

* no message

* no message
  • Loading branch information
mmeyer2k authored Mar 5, 2020
1 parent 893d0a7 commit ad37f76
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 176 deletions.
24 changes: 8 additions & 16 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ jobs:
- checkout
- restore_cache:
keys:
- source-php7.1-{{ .Branch }}-{{ .Revision }}
- source-php7.1-{{ .Branch }}-
- source-php7.1-
- php7.1-{{ .Branch }}
- run: composer require phpunit/phpunit infection/infection phpmetrics/phpmetrics
- run: mkdir -p coverage
- run: ./vendor/bin/phpunit --coverage-html coverage --coverage-clover=coverage.clover
Expand All @@ -19,7 +17,7 @@ jobs:
- run: wget https://scrutinizer-ci.com/ocular.phar
- run: php ocular.phar code-coverage:upload --format=php-clover coverage.clover
- save_cache:
key: source-php7.1-{{ .Branch }}-{{ .Revision }}
key: php7.1-{{ .Branch }}
paths:
- vendor
- store_artifacts:
Expand All @@ -36,13 +34,11 @@ jobs:
- checkout
- restore_cache:
keys:
- source-php7.2-{{ .Branch }}-{{ .Revision }}
- source-php7.2-{{ .Branch }}-
- source-php7.2-
- php7.2-{{ .Branch }}
- run: composer require phpunit/phpunit
- run: php vendor/phpunit/phpunit/phpunit
- save_cache:
key: source-php7.2-{{ .Branch }}-{{ .Revision }}
key: php7.2-{{ .Branch }}
paths:
- vendor

Expand All @@ -53,13 +49,11 @@ jobs:
- checkout
- restore_cache:
keys:
- source-php7.3-{{ .Branch }}-{{ .Revision }}
- source-php7.3-{{ .Branch }}-
- source-php7.3-
- php7.3-{{ .Branch }}
- run: composer require phpunit/phpunit
- run: php vendor/phpunit/phpunit/phpunit
- save_cache:
key: source-php7.3-{{ .Branch }}-{{ .Revision }}
key: php7.3-{{ .Branch }}
paths:
- vendor
php-74:
Expand All @@ -69,13 +63,11 @@ jobs:
- checkout
- restore_cache:
keys:
- source-php7.4-{{ .Branch }}-{{ .Revision }}
- source-php7.4-{{ .Branch }}-
- source-php7.4-
- php7.4-{{ .Branch }}
- run: composer require phpunit/phpunit
- run: php vendor/phpunit/phpunit/phpunit
- save_cache:
key: source-php7.4-{{ .Branch }}-{{ .Revision }}
key: php7.4-{{ .Branch }}
paths:
- vendor

Expand Down
2 changes: 0 additions & 2 deletions .styleci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ preset: recommended
risky: true

enabled:
- array_indentation
- unalign_double_arrow
- ternary_to_null_coalescing
- no_alternative_syntax
- concat_with_spaces

disabled:
Expand Down
57 changes: 24 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@ For legacy PHP version support, look [here](https://github.com/mmeyer2k/dcrypt/b
If you need a dcrypt inspired encryption library for .NET, check out [harpocrates](https://github.com/mmeyer2k/harpocrates).

- [Install](#install)
- [Features](#features)
- [Block Ciphers](#block-ciphers)
- [AES-256 GCM Encryption](#aes-256-gcm-encryption)
- [Other AES-256 Modes](#other-aes-256-modes)
- [Custom Encryption Suites](#custom-encryption-suites)
- [Static Wrapper](#static-wrapper)
- [Class Overloading](#class-overloading)
- [Layered Encryption Factory](#layered-encryption-factory)
- [Message Authenticity Checking](#message-authenticity-checking)
- [Stream Ciphers](#stream-ciphers)
- [One Time Pad](#one-time-pad)
- [Block Ciphers](#block-ciphers)
- [AES-256 GCM Encryption](#aes-256-gcm-encryption)
- [Other AES-256 Modes](#other-aes-256-modes)
- [Custom Encryption Suites](#custom-encryption-suites)
- [Static Wrapper](#static-wrapper)
- [Class Overloading](#class-overloading)
- [Layered Encryption Factory](#layered-encryption-factory)
- [Message Authenticity Checking](#message-authenticity-checking)
- [Stream Ciphers](#stream-ciphers)
- [One Time Pad](#one-time-pad)
- [Show me some love](#show-me-some-love-heart_eyes) :heart_eyes::beer:

# Install
Expand All @@ -35,38 +34,30 @@ Don't worry, dcrypt does not have any dependencies of its own.
composer require "mmeyer2k/dcrypt=^13.0"
```

# Features

## Block Ciphers

The dcrypt library helps application developers avoid common mistakes in crypto implementations that leave data at risk while still providing flexibility in its options for crypto enthusiasts.
Dcrypt strives to make correct usage simple, but it _is_ possible to use dcrypt incorrectly.
Fully understanding the instructions is important.

Dcrypt's functions __require__ the use of a high entropy __2048 byte__ (minimum) key encoded with base64.
Dcrypt's block cipher functions require the use of a high entropy 256 bit, base64-encoded key.
To generate a new key, execute this on the command line:

```bash
head -c 2048 /dev/urandom | base64 -w 0 | xargs echo
head -c 32 /dev/urandom | base64 -w 0 | xargs echo
```

Storing this key safely is up to you! [Guide to keys](https://github.com/mmeyer2k/dcrypt/blob/master/docs/KEYS.md).

[Specification document](https://github.com/mmeyer2k/dcrypt/blob/master/docs/CRYPTO.md)


### AES-256 GCM Encryption

Since PHP 7.1 supports native AEAD encryption modes, using GCM would be safest option for most applications.
Dcrypt will handle the AEAD authentication tag, SHA3-256 HMAC ([Keccak](https://en.wikipedia.org/wiki/SHA-3)), initialization vector and encrypted message as a single unencoded string.

```php
<?php
$key = "replace this with the output of: head -c 2048 /dev/urandom | base64 -w 0 | xargs echo";
$key = "..............................";

$encrypted = \Dcrypt\Aes256Gcm::encrypt('a secret', $key);
$encrypted = \Dcrypt\Aes::encrypt('a secret', $key);

$plaintext = \Dcrypt\Aes256Gcm::decrypt($encrypted, $key);
$plaintext = \Dcrypt\Aes::decrypt($encrypted, $key);
```

**If in doubt, use this example and don't read any further!**
Expand All @@ -77,15 +68,15 @@ If you read to this point then you are an experienced cryptonaut, congrats! :ok_

Several AES-256 encryption modes are supported out of the box via hardcoded classes.

| Class Name | OpenSSL Cipher | Security Rating | Further Reading |
| -------------------- | :--------------: | :---------------: | --------------- |
| `\Dcrypt\Aes256Gcm` | `aes-256-gcm` | :smiley: | [wiki](https://en.wikipedia.org/wiki/Galois/Counter_Mode) |
| `\Dcrypt\Aes256Ctr` | `aes-256-ctr` | :relaxed: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)) |
| `\Dcrypt\Aes256Cbc` | `aes-256-cbc` | :expressionless: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) |
| `\Dcrypt\Aes256Ofb` | `aes-256-ofb` | :grimacing: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_Feedback_(OFB)) |
| `\Dcrypt\Aes256Cfb` | `aes-256-cfb` | :hushed: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)) |
| `\Dcrypt\Aes256Ccm` | `aes-256-ccm` | :astonished: | [wiki](https://en.wikipedia.org/wiki/CCM_mode) |
| `\Dcrypt\Aes256Ecb` | `aes-256-ecb` | :rage: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#ECB) |
| Class Name | OpenSSL Cipher | Security Rating | Further Reading |
| -------------------- | :--------------: | :---------------: | --------------- |
| `Aes256Gcm` or `Aes` | `aes-256-gcm` | :smiley: | [wiki](https://en.wikipedia.org/wiki/Galois/Counter_Mode) |
| `Aes256Ctr` | `aes-256-ctr` | :relaxed: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)) |
| `Aes256Cbc` | `aes-256-cbc` | :expressionless: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) |
| `Aes256Ofb` | `aes-256-ofb` | :grimacing: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_Feedback_(OFB)) |
| `Aes256Cfb` | `aes-256-cfb` | :hushed: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)) |
| `Aes256Ccm` | `aes-256-ccm` | :astonished: | [wiki](https://en.wikipedia.org/wiki/CCM_mode) |
| `Aes256Ecb` | `aes-256-ecb` | :rage: | [wiki](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#ECB) |

### Custom Encryption Suites

Expand Down
6 changes: 6 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changes in Dcrypt

## 13.1.0
- Only require 32 byte keys from now on
- Remove key randomness testing in favor of trusting devs
- Add "Aes" as shorthand alias for "Aes256Gcm" to prevent typos
-

## 13.0.0
- Skip validating key when decrypting
- Clean up internal API
Expand Down
83 changes: 0 additions & 83 deletions docs/KEYS.md

This file was deleted.

32 changes: 32 additions & 0 deletions src/Aes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

/**
* Aes.php.
*
* PHP version 7
*
* @category Dcrypt
*
* @author Michael Meyer (mmeyer2k) <m.meyer2k@gmail.com>
* @license http://opensource.org/licenses/MIT The MIT License (MIT)
*
* @link https://github.com/mmeyer2k/dcrypt
*/

namespace Dcrypt;

/**
* A shorthand alias for Aes256Gcm to prevent typos and make neater code.
*
* @category Dcrypt
*
* @author Michael Meyer (mmeyer2k) <m.meyer2k@gmail.com>
* @license http://opensource.org/licenses/MIT The MIT License (MIT)
*
* @link https://github.com/mmeyer2k/dcrypt
*/
class Aes extends Aes256Gcm
{
}
3 changes: 1 addition & 2 deletions src/Exceptions/InvalidKeyException.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,5 @@
*/
class InvalidKeyException extends \Exception
{
const KEYLENGTH = 'Key must be at least 2048 bytes and base64 encoded';
const KEYRANDOM = 'Key does not contain the minimum amount of entropy';
const KEYLENGTH = 'Key must be at least 32 bytes';
}
38 changes: 8 additions & 30 deletions src/OpensslKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,32 +55,22 @@ final class OpensslKey
/**
* OpensslKey constructor.
*
* @param string $algo Algo to use for HKDF
* @param string $key Key
* @param string $ivr Initialization vector
* @param bool $testKey Validate the key
* @param string $algo Algo to use for HKDF
* @param string $key Key to use for encryption
* @param string $ivr Initialization vector
*
* @throws InvalidKeyException
*/
public function __construct(
string $algo,
string $key,
string $ivr = '',
bool $testKey = true
string $ivr = ''
) {
// Store the key as what was supplied
$this->_key = \base64_decode($key);

if ($testKey) {
// Make sure key was properly decoded and meets minimum required length
if (Str::strlen($this->_key) < 2048) {
throw new InvalidKeyException(InvalidKeyException::KEYLENGTH);
}

// Make sure key meets minimum entropy requirement
if (self::_testKeyEntropy($this->_key) === false) {
throw new InvalidKeyException(InvalidKeyException::KEYRANDOM);
}
if (Str::strlen($this->_key) < 32) {
throw new InvalidKeyException(InvalidKeyException::KEYLENGTH);
}

// Store algo in object
Expand Down Expand Up @@ -135,24 +125,12 @@ public function deriveKey(string $info): string
*
* @return string
*/
public static function create(int $bytes = 2048): string
public static function create(int $bytes = 32): string
{
if ($bytes < 2048) {
if ($bytes < 32) {
throw new InvalidKeyException(InvalidKeyException::KEYLENGTH);
}

return \base64_encode(\random_bytes($bytes));
}

/**
* Returns true if key has enough entropy.
*
* @param string $key Key string to test
*
* @return bool
*/
private static function _testKeyEntropy(string $key): bool
{
return \count(\array_unique(\str_split($key))) > 250;
}
}
4 changes: 2 additions & 2 deletions src/OpensslStatic.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public static function decrypt(
// Get the encrypted message payload
$msg = Str::substr($data, $isz + $hsz + $tsz);

// Create key derivation object (key testing = false)
$key = new OpensslKey($algo, $key, $ivr, false);
// Create key derivation object
$key = new OpensslKey($algo, $key, $ivr);

// Calculate checksum of message payload for verification
$chk = \hash_hmac($algo, $msg, $key->authenticationKey($cipher), true);
Expand Down
Loading

0 comments on commit ad37f76

Please sign in to comment.