PHPackages                             ricwein/crypto - 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. ricwein/crypto

ActiveLibrary[Security](/categories/security)

ricwein/crypto
==============

libsodium based cryptography library

2.1.1(5y ago)11.9k[1 PRs](https://github.com/ricwein/Crypto/pulls)MITPHPPHP &gt;= 8.0

Since Jul 19Pushed 1y ago1 watchersCompare

[ Source](https://github.com/ricwein/Crypto)[ Packagist](https://packagist.org/packages/ricwein/crypto)[ RSS](/packages/ricwein-crypto/feed)WikiDiscussions master Synced 6d ago

READMEChangelog (10)Dependencies (4)Versions (12)Used By (0)

Crypto
======

[](#crypto)

This library wraps the PHP libsodium cryptographic functions into an object-orientated api, allowing a simple and safe usage.

This library provides:

- symmetric and asymmetric authenticated en/decryption of messages and files using **XSalsa20**
- cryptographic secure key and keypair generation
- Diffie Hellman key-exchange for keypairs using Curve25519 (**X25519**)
- ex/import of keys and ciphertexts with support for most common encodings

Installation
============

[](#installation)

```
composer require ricwein/crypto
```

All classes uses the root-namespace `ricwein\Crypto`. All thrown Exceptions extend from `ricwein\Crypto\Exceptions\Exception`.

Symmetric Crypto
----------------

[](#symmetric-crypto)

Symmetric cryptography uses a secret (key) to encrypt a given message to a ciphertext, and the same secret to decrypt the ciphertext to the original message again.

### encrypt

[](#encrypt)

```
use ricwein\Crypto\Symmetric\Crypto;
use ricwein\Crypto\Symmetric\Key;
use ricwein\Crypto\Exceptions\Exception as CryptoException;

try {
    $message = 'asecretmessage';
    $key = Key::generate();

    // actual encryption
    $ciphertext = (new Crypto($key))->encrypt($message);

    // now we can use the resulting key and ciphertext, e.g. safe them to the filesystem
    file_put_contents(__DIR__ . '/key', $key->getKey());
    file_put_contents(__DIR__ . '/message', $ciphertext->getString());

} catch (CryptoException $e) {
    // something went wrong
}
```

### decrypt

[](#decrypt)

```
use ricwein\Crypto\Ciphertext;
use ricwein\Crypto\Symmetric\Crypto;
use ricwein\Crypto\Symmetric\Key;
use ricwein\Crypto\Exceptions\Exception as CryptoException;
use ricwein\Crypto\Exceptions\MacMismatchException;

try {
    $ciphertext = Ciphertext::fromString(file_get_contents(__DIR__ . '/message'));
    $key = Key::load(file_get_contents(__DIR__ . '/key'));

    // actual decryption
    $plaintext = (new Crypto($key))->decrypt($ciphertext);

} catch (MacMismatchException $e) {
    // unable to decrypt message, invalid HMAC
} catch (CryptoException $e) {
    // something else went wrong
}
```

Asymmetric Crypto
-----------------

[](#asymmetric-crypto)

Asymmetric Crypto uses keypairs out of a public, and a private key to encrypt and sign messages.

**sending:** Usually a Message is encrypted with the public-key of the receiver, and signed with the private-key of the sender.

**receiving:** The receiver is than able to verify the message-signature ((H)MAC) with the public-key of the sender and can decrypt it with its own private-key.

> The following example uses two keypairs (alice and bob) with known private-keys in the same code-scope. This is just done for comprehensibility. In real-world cases on side only knowns it's own private-key (public is not required) and the public-key of the other participant.

### encrypt

[](#encrypt-1)

```
use ricwein\Crypto\Asymmetric\Crypto;
use ricwein\Crypto\Asymmetric\KeyPair;
use ricwein\Crypto\Exceptions\Exception as CryptoException;

try {
    $message = 'asecretmessage';
    $keyAlice = KeyPair::generate();
    $keyBob = KeyPair::generate();

    // send message from alice to bob
    $ciphertext = (new Crypto($keyAlice))->encrypt($message, $keyBob->getKey(KeyPair::PUB_KEY));

    // it's enough to store the private-keys of our keypairs, public-keys can be derived later if required
    file_put_contents(__DIR__ . '/alice.key', $keyAlice->getKey(KeyPair::PRIV_KEY));
    file_put_contents(__DIR__ . '/bob.key', $keyBob->getKey(KeyPair::PRIV_KEY));
    file_put_contents(__DIR__ . '/message', $ciphertext->getString());

} catch (CryptoException $e) {
    // something went wrong
}
```

### decrypt

[](#decrypt-1)

```
use ricwein\Crypto\Ciphertext;
use ricwein\Crypto\Asymmetric\Crypto;
use ricwein\Crypto\Asymmetric\KeyPair;
use ricwein\Crypto\Exceptions\Exception as CryptoException;
use ricwein\Crypto\Exceptions\MacMismatchException;

try {
    $keyAlice = KeyPair::load([
        KeyPair::PRIV_KEY => file_get_contents(__DIR__ . '/alice.key')
    ]);
    $keyBob = KeyPair::load([
        KeyPair::PRIV_KEY => file_get_contents(__DIR__ . '/bob.key')
    ]);
    $ciphertext = Ciphertext::fromString(file_get_contents(__DIR__ . '/message'));

    // verify and decrypt the ciphertext
    // it's enough to pass alice keypair with only a private key here,
    // the public key will be dynamically derived to verify the ciphertexts HMAC
    // BUT you can also directly pass alice public-key
    $plaintext = (new Crypto($keyBob))->decrypt($ciphertext, $keyAlice);

} catch (MacMismatchException $e) {
    // unable to decrypt message, invalid HMAC for alice
} catch (CryptoException $e) {
    // something else went wrong
}
```

Encoding
========

[](#encoding)

Key-ex/import and ciphertext ex/import supports four types of encoding, provided by `ricwein\Crypto\Encoding`.

File-Crypto
===========

[](#file-crypto)

This library also provides RAM-friendly file-en/decrypting using stream-encryption. To use the integrated file-crypto, the `ricwein/filesystem` library is required. It can be installed with:

```
composer require ricwein/filesystem
```

The usage is the same as the sym/asymmetric en/decryption methods, but instead of encrypting strings into ciphertexts-objects, a File will be encrypted, returning a new File-Object.

Most times it's useful to encrypt a file and replace its plaintext with the new ciphertext. It should be noted, that this library creates a temp-file in this case, encrypts the sourcefile into the new temp-file, and replaces the source afterwards with the temp-file.

All file-crypto methods support custom destination storages, which can be provided as the last parameter in `encryptFile()` and `decryptFile()`. If a storage is given, the previously described encryption through a temp-file is skipped.

Symmetric Crypto
----------------

[](#symmetric-crypto-1)

### encrypt

[](#encrypt-2)

```
use ricwein\Crypto\Symmetric\Crypto;
use ricwein\Crypto\Symmetric\Key;
use ricwein\Crypto\Exceptions\Exception as CryptoException;
use ricwein\FileSystem\Exceptions\Exception as FileException;
use ricwein\FileSystem\File;
use ricwein\FileSystem\Storage;

try {
    $file = new File(new Storage\Disk(__DIR__, 'file.txt'));
    $key = Key::generate();

    // actual encryption
    $encryptedFile = (new Crypto($key))->encryptFile($file);
    file_put_contents(__DIR__ . '/key', $key->getKey());

} catch (FileException $e) {
    // unable to open, read or write the file
} catch (CryptoException $e) {
    // something went wrong
}
```

### decrypt

[](#decrypt-2)

```
use ricwein\Crypto\Symmetric\Crypto;
use ricwein\Crypto\Symmetric\Key;
use ricwein\Crypto\Exceptions\Exception as CryptoException;
use ricwein\Crypto\Exceptions\MacMismatchException;
use ricwein\FileSystem\Exceptions\Exception as FileException;
use ricwein\FileSystem\File;
use ricwein\FileSystem\Storage;

try {
    $encryptedFile = new File(new Storage\Disk(__DIR__, 'file.txt'));
    $key = Key::load(file_get_contents(__DIR__ . '/key'));

    // actual decryption
    $file = (new Crypto($key))->decryptFile($encryptedFile);

} catch (MacMismatchException $e) {
    // unable to decrypt message, invalid HMAC
} catch (FileException $e) {
    // unable to open, read or write the file
} catch (CryptoException $e) {
    // something else went wrong
}
```

Asymmetric Crypto
-----------------

[](#asymmetric-crypto-1)

> The following example uses two keypairs (alice and bob) with known private-keys in the same code-scope. This is just done for comprehensibility. In real-world cases, one side only knows its own private-key (public is not required) and the public-key of the other participant.

### encrypt

[](#encrypt-3)

```
use ricwein\Crypto\Asymmetric\Crypto;
use ricwein\Crypto\Asymmetric\KeyPair;
use ricwein\Crypto\Exceptions\Exception as CryptoException;
use ricwein\FileSystem\Exceptions\Exception as FileException;
use ricwein\FileSystem\File;
use ricwein\FileSystem\Storage;

try {
    $file = new File(new Storage\Disk(__DIR__, 'file.txt'));
    $keyAlice = KeyPair::generate();
    $keyBob = KeyPair::generate();

    $plainTextFile = new File(new Storage\Disk(__DIR__, 'file.txt'));

    // send message from alice to bob
    $encryptedFile = (new Crypto($keyAlice))->encryptFile($plainTextFile, null, $keyBob);

    // it's enough to store the private-keys of our keypairs, public-keys can be derived later if required
    file_put_contents(__DIR__ . '/alice.key', $keyAlice->getKey(KeyPair::PRIV_KEY));
    file_put_contents(__DIR__ . '/bob.key', $keyBob->getKey(KeyPair::PRIV_KEY));

} catch (FileException $e) {
    // unable to open, read or write the file
} catch (CryptoException $e) {
    // something went wrong
}
```

### decrypt

[](#decrypt-3)

```
use ricwein\Crypto\Asymmetric\Crypto;
use ricwein\Crypto\Asymmetric\KeyPair;
use ricwein\Crypto\Exceptions\Exception as CryptoException;
use ricwein\Crypto\Exceptions\MacMismatchException;
use ricwein\FileSystem\Exceptions\Exception as FileException;
use ricwein\FileSystem\File;
use ricwein\FileSystem\Storage;

try {
    $keyAlice = KeyPair::load([
        KeyPair::PRIV_KEY => file_get_contents(__DIR__ . '/alice.key')
    ]);
    $keyBob = KeyPair::load([
        KeyPair::PRIV_KEY => file_get_contents(__DIR__ . '/bob.key')
    ]);

    $encryptedFile = new File(new Storage\Disk(__DIR__, 'file.txt'));

    $file = (new Crypto($keyBob))->decryptFile($encryptedFile, null, $keyAlice);

} catch (MacMismatchException $e) {
    // unable to decrypt message, invalid HMAC for alice
} catch (FileException $e) {
    // unable to open, read or write the file
} catch (CryptoException $e) {
    // something else went wrong
}
```

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance30

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity74

Established project with proven stability

 Bus Factor1

Top contributor holds 100% 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 ~112 days

Recently: every ~96 days

Total

10

Last Release

1847d ago

Major Versions

1.2.1 → 2.0.02021-04-23

PHP version history (3 changes)1.0PHP &gt;= 7.2.0

1.2.0PHP &gt;= 7.4.0

2.0.0PHP &gt;= 8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/1e4c46b9e849423ff1355ff0a8dc5046c29e636308378f44ed0a55933f749e83?d=identicon)[ricwein](/maintainers/ricwein)

---

Top Contributors

[![ricwein](https://avatars.githubusercontent.com/u/870354?v=4)](https://github.com/ricwein "ricwein (23 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ricwein-crypto/health.svg)

```
[![Health](https://phpackages.com/badges/ricwein-crypto/health.svg)](https://phpackages.com/packages/ricwein-crypto)
```

###  Alternatives

[phpseclib/phpseclib

PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.

5.6k434.8M1.3k](/packages/phpseclib-phpseclib)[paragonie/paseto

Platform-Agnostic Security Tokens

3.4k1.3M18](/packages/paragonie-paseto)[paragonie/ciphersweet

Searchable field-level encryption library for relational databases

4641.2M21](/packages/paragonie-ciphersweet)[paragonie/certainty

Up-to-date, verifiable repository for Certificate Authorities

2642.4M20](/packages/paragonie-certainty)[paragonie/hidden-string

Encapsulate strings in an object to hide them from stack traces

7410.6M39](/packages/paragonie-hidden-string)[paragonie/anti-csrf

Paragon Initiative's Anti-CSRF Security Library

307200.6k5](/packages/paragonie-anti-csrf)

PHPackages © 2026

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