PHPackages                             monkeyscloud/monkeyslegion-encryption - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. monkeyscloud/monkeyslegion-encryption

ActiveLibrary[Security](/categories/security)

monkeyscloud/monkeyslegion-encryption
=====================================

Standalone encryption for MonkeysLegion v2 — AES-GCM, XChaCha20, HMAC, key rotation, envelope encryption, PHP 8.4 hooks

1.0.1(1mo ago)03151MITPHPPHP ^8.4

Since May 26Pushed 1mo agoCompare

[ Source](https://github.com/MonkeysCloud/MonkeysLegion-Encryption)[ Packagist](https://packagist.org/packages/monkeyscloud/monkeyslegion-encryption)[ RSS](/packages/monkeyscloud-monkeyslegion-encryption/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (4)Versions (3)Used By (1)

MonkeysLegion Encryption
========================

[](#monkeyslegion-encryption)

Enterprise-grade **standalone cryptography** for the MonkeysLegion v2 framework.

AES-256-GCM • XChaCha20-Poly1305 • HMAC signing • key rotation • envelope encryption • deterministic encryption • HKDF key derivation • password hashing • PHP 8.4 property hooks • PHPStan Level 9

---

Installation
------------

[](#installation)

```
composer require monkeyscloud/monkeyslegion-encryption
```

**Requirements:** PHP ≥ 8.4 · ext-openssl · ext-sodium · ext-mbstring

---

Quick Start
-----------

[](#quick-start)

```
use MonkeysLegion\Encryption\Encrypter;
use MonkeysLegion\Encryption\Key\Key;

$key = Key::generate();
$encrypter = new Encrypter($key);

$encrypted = $encrypter->encryptString('sensitive data');
$decrypted = $encrypter->decryptString($encrypted); // "sensitive data"
```

---

Supported Ciphers
-----------------

[](#supported-ciphers)

```
use MonkeysLegion\Encryption\Enum\Cipher;

Cipher::Aes128Cbc         // AES-128-CBC + HMAC-SHA256
Cipher::Aes256Cbc         // AES-256-CBC + HMAC-SHA256
Cipher::Aes128Gcm         // AES-128-GCM (AEAD)
Cipher::Aes256Gcm         // AES-256-GCM (AEAD) — DEFAULT
Cipher::XChaCha20Poly1305 // XChaCha20-Poly1305 (libsodium AEAD)
```

```
// Use a specific cipher
$key = Key::generate(Cipher::XChaCha20Poly1305);
$encrypter = new Encrypter($key, Cipher::XChaCha20Poly1305);
```

---

Key Generation
--------------

[](#key-generation)

```
use MonkeysLegion\Encryption\Key\{Key, KeyGenerator};
use MonkeysLegion\Encryption\Enum\Cipher;

// Generate a key
$key = Key::generate();                          // AES-256-GCM default
$key = Key::generate(Cipher::XChaCha20Poly1305); // Sodium

// Output formats
echo $key->base64(); // "base64:r4nd0m..."
echo $key->hex();    // "6162636465..."

// From existing key
$key = Key::fromBase64('base64:YOUR_KEY_HERE');
$key = Key::fromRaw($rawBytes, Cipher::Aes256Gcm);

// Static generator
$base64 = KeyGenerator::generateBase64();
$hex    = KeyGenerator::generateHex(Cipher::XChaCha20Poly1305);

// Memory safety
$key->destroy();              // Wipes key material from memory
$key->isDestroyed();          // true
```

---

Key Rotation (Graceful)
-----------------------

[](#key-rotation-graceful)

```
use MonkeysLegion\Encryption\Key\{Key, KeyChain};
use MonkeysLegion\Encryption\Encrypter;

$currentKey = Key::fromBase64($newKeyString);
$oldKey     = Key::fromBase64($previousKeyString);

$keyChain = KeyChain::withRotation($currentKey, [$oldKey]);
$encrypter = new Encrypter($keyChain);

// New data encrypted with current key
$encrypted = $encrypter->encryptString('new data');

// Old data decrypted by trying all keys (current → previous)
$decrypted = $encrypter->decryptString($oldEncryptedPayload);

// Property hooks
$encrypter->usingRotation;      // true
$keyChain->hasPreviousKeys;     // true
$keyChain->keyCount;            // 2
```

---

Envelope Encryption (Per-Record Keys)
-------------------------------------

[](#envelope-encryption-per-record-keys)

```
use MonkeysLegion\Encryption\EnvelopeEncrypter;

$envelope = new EnvelopeEncrypter($masterKey);

// Encrypt — generates random DEK per record
$result = $envelope->encrypt('patient medical records');
// ['encrypted_data' => '...', 'wrapped_key' => '...', 'cipher' => 'aes-256-gcm']

// Decrypt — unwraps DEK then decrypts data
$data = $envelope->decrypt($result);

// Re-wrap with new master key (zero-downtime rotation)
$newResult = $envelope->rewrap($result, $newMasterKey);
```

---

Deterministic Encryption (Searchable Fields)
--------------------------------------------

[](#deterministic-encryption-searchable-fields)

```
use MonkeysLegion\Encryption\DeterministicEncrypter;

$det = new DeterministicEncrypter($key);

// Same input → same output (for indexed DB columns)
$a = $det->encrypt('user@example.com');
$b = $det->encrypt('user@example.com');
assert($a === $b); // true — searchable!

$email = $det->decrypt($a); // "user@example.com"
```

> ⚠️ **WARNING:** Less secure than random-IV encryption. Use only for searchable indexed fields.

---

HMAC Signing
------------

[](#hmac-signing)

```
use MonkeysLegion\Encryption\Hmac\HmacSigner;
use MonkeysLegion\Encryption\Enum\HmacAlgorithm;

$signer = new HmacSigner($secretKey);

// Sign
$mac = $signer->sign('webhook payload');

// Verify (constant-time comparison)
$valid = $signer->verify('webhook payload', $mac); // true

// Different algorithms
$mac512 = $signer->sign('data', null, HmacAlgorithm::Sha512);

// Structured result
$result = $signer->signResult('data');
echo $result->mac;
echo $result->length;
$result->verify($incomingMac);
```

---

Password Hashing
----------------

[](#password-hashing)

```
use MonkeysLegion\Encryption\Hash\Hasher;
use MonkeysLegion\Encryption\Enum\HashAlgorithm;

// Default: Argon2id
$hasher = new Hasher();
$hash = $hasher->hash('my-password');
$valid = $hasher->verify('my-password', $hash); // true

// Check if needs upgrade
if ($hasher->needsRehash($hash)) {
    $newHash = $hasher->hash('my-password');
}

// Hash info
$info = $hasher->info($hash);
$info->isArgon2;  // true (property hook)
$info->isBcrypt;  // false (property hook)

// Bcrypt with custom rounds
$bcrypt = new Hasher(HashAlgorithm::Bcrypt, ['rounds' => 14]);

// Argon2id with custom options
$argon = new Hasher(HashAlgorithm::Argon2id, [
    'memory'  => 131072,
    'time'    => 6,
    'threads' => 4,
]);
```

---

Key Derivation (HKDF)
---------------------

[](#key-derivation-hkdf)

```
use MonkeysLegion\Encryption\Key\{Key, KeyDerivation};

$kdf = new KeyDerivation(salt: random_bytes(16));
$masterKey = Key::generate();

// Derive sub-keys with context labels
$encKey  = $kdf->deriveKey($masterKey, 'encryption-v1');
$authKey = $kdf->deriveKey($masterKey, 'authentication-v1');

// Use derived keys
$encrypter = new Encrypter($encKey->toKey());

// Raw derivation
$raw = $kdf->derive($masterKey->material(), 'session-key', 32);
```

---

Property Hooks (PHP 8.4)
------------------------

[](#property-hooks-php-84)

```
// Key
$key->length;      // int (hook)
$key->isValid;     // bool (hook)

// KeyChain
$chain->hasPreviousKeys; // bool (hook)
$chain->keyCount;        // int (hook)

// DerivedKey
$dk->length;    // int (hook)
$dk->isValid;   // bool (hook)

// Encrypter
$enc->cipher;         // Cipher enum (hook)
$enc->usingRotation;  // bool (hook)

// EncryptionResult
$result->isAead;    // bool (hook)
$result->isSodium;  // bool (hook)

// HashInfo
$info->isBcrypt;  // bool (hook)
$info->isArgon2;  // bool (hook)
$info->isKnown;   // bool (hook)

// HmacResult
$hmac->length;  // int (hook)
```

---

`#[Encrypted]` Attribute (Entity-Level Encryption)
--------------------------------------------------

[](#encrypted-attribute-entity-level-encryption)

```
use MonkeysLegion\Encryption\Attribute\Encrypted;
use MonkeysLegion\Encryption\Enum\Cipher;

class Patient
{
    #[Encrypted]
    public string $ssn;                              // Auto-encrypt/decrypt

    #[Encrypted(cipher: Cipher::XChaCha20Poly1305)]
    public string $medicalRecord;                    // Custom cipher per field

    #[Encrypted(deterministic: true)]
    public string $email;                            // Searchable encrypted field

    #[Encrypted(keyId: 'tenant-key')]
    public string $apiSecret;                        // Multi-tenant key isolation
}

// Property hooks
$attr = new Encrypted(deterministic: true);
$attr->isSearchable;    // true  (hook)
$attr->hasCustomCipher; // false (hook)
```

> 💡 **Competitive:** This is MonkeysLegion's answer to Laravel's `encrypted` cast — but attribute-first, per-field cipher selection, and searchable (deterministic) mode built-in.

---

`#[Hashed]` Attribute (Password Fields)
---------------------------------------

[](#hashed-attribute-password-fields)

```
use MonkeysLegion\Encryption\Attribute\Hashed;
use MonkeysLegion\Encryption\Enum\HashAlgorithm;

class User
{
    #[Hashed]
    public string $password;                          // Auto-hash (Argon2id default)

    #[Hashed(algorithm: HashAlgorithm::Bcrypt, options: ['rounds' => 14])]
    public string $pin;                               // Bcrypt with custom cost

    #[Hashed(algorithm: HashAlgorithm::Argon2i)]
    public string $legacyPassword;                    // Argon2i
}

// Property hooks
$attr = new Hashed();
$attr->isArgon;  // true
$attr->isBcrypt; // false
```

---

`Crypt` Static Facade
---------------------

[](#crypt-static-facade)

```
use MonkeysLegion\Encryption\Crypt;
use MonkeysLegion\Encryption\Encrypter;
use MonkeysLegion\Encryption\Key\Key;

// Bootstrap (done once by the framework)
$key = Key::fromBase64(getenv('ENCRYPTION_KEY'));
Crypt::setInstance(new Encrypter($key));

// Application code — clean, static API
$encrypted = Crypt::encryptString('api-token-xyz');
$decrypted = Crypt::decryptString($encrypted);

// With serialization
$encrypted = Crypt::encrypt(['user_id' => 42]);
$data      = Crypt::decrypt($encrypted);

// Access the key
$key = Crypt::getKey();

// Reset for tests
Crypt::reset();
```

---

Testing (Fakes)
---------------

[](#testing-fakes)

```
use MonkeysLegion\Encryption\Testing\{FakeEncrypter, FakeHasher};

// FakeEncrypter — reversible base64 round-trip
$fake = new FakeEncrypter($key);
$encrypted = $fake->encryptString('hello');
$decrypted = $fake->decryptString($encrypted); // "hello"

$fake->encryptCount();  // 1
$fake->decryptCount();  // 1
$fake->assertNothingEncrypted(); // throws if any operations recorded

// FakeHasher — plaintext round-trip
$hasher = new FakeHasher();
$hash = $hasher->hash('password');        // "fakehash:password"
$hasher->verify('password', $hash);       // true
```

---

CLI Commands
------------

[](#cli-commands)

```
# Generate a new key
php ml encryption:generate-key
php ml encryption:generate-key --cipher=xchacha20-poly1305
php ml encryption:generate-key --format=hex

# Rotate key (with instructions)
php ml encryption:rotate-key
```

---

DI Integration
--------------

[](#di-integration)

```
use MonkeysLegion\Encryption\Provider\EncryptionProvider;

$services = EncryptionProvider::register([
    'cipher' => 'aes-256-gcm',
    'key'    => 'base64:YOUR_KEY',
    'previous_keys' => 'base64:OLD_KEY_1,base64:OLD_KEY_2',
    'hash' => [
        'algorithm' => 'argon2id',
        'memory'    => 65536,
        'time'      => 4,
        'threads'   => 4,
    ],
    'hmac' => [
        'key' => 'your-hmac-key',
    ],
]);

$encrypter = $services['encrypter']; // EncrypterInterface
$hasher    = $services['hasher'];    // HasherInterface
$hmac      = $services['hmac'];     // HmacInterface
```

---

Configuration (`config/encryption.mlc`)
---------------------------------------

[](#configuration-configencryptionmlc)

```
encryption {
    cipher        = ${ENCRYPTION_CIPHER:-aes-256-gcm}
    key           = ${ENCRYPTION_KEY}
    previous_keys = ${ENCRYPTION_PREVIOUS_KEYS:-}

    hash {
        algorithm = ${HASH_ALGO:-argon2id}
        bcrypt_rounds = ${BCRYPT_ROUNDS:-12}
        argon_memory  = ${ARGON_MEMORY:-65536}
        argon_threads = ${ARGON_THREADS:-4}
        argon_time    = ${ARGON_TIME:-4}
    }

    hmac {
        algorithm = ${HMAC_ALGO:-sha256}
        key       = ${HMAC_KEY:-}
    }
}

```

---

License
-------

[](#license)

MIT © 2026 MonkeysCloud Team

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance90

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 50% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~9 days

Total

2

Last Release

50d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2913369?v=4)[Jorge Peraza](/maintainers/yorchperaza)[@yorchperaza](https://github.com/yorchperaza)

---

Top Contributors

[![Amanar-Marouane](https://avatars.githubusercontent.com/u/155680356?v=4)](https://github.com/Amanar-Marouane "Amanar-Marouane (1 commits)")[![yorchperaza](https://avatars.githubusercontent.com/u/2913369?v=4)](https://github.com/yorchperaza "yorchperaza (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/monkeyscloud-monkeyslegion-encryption/health.svg)

```
[![Health](https://phpackages.com/badges/monkeyscloud-monkeyslegion-encryption/health.svg)](https://phpackages.com/packages/monkeyscloud-monkeyslegion-encryption)
```

###  Alternatives

[mews/purifier

Laravel 5/6/7/8/9/10 HtmlPurifier Package

2.0k18.7M144](/packages/mews-purifier)[paragonie/ecc

PHP Elliptic Curve Cryptography library

24820.0k41](/packages/paragonie-ecc)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
