All Projects → jedisct1 → Libsodium Php

jedisct1 / Libsodium Php

Licence: bsd-2-clause
The PHP extension for libsodium.

Programming Languages

c
50402 projects - #5 most used programming language

Projects that are alternatives of or similar to Libsodium Php

Streamcryptor
Stream encryption & decryption with libsodium and protobuf
Stars: ✭ 112 (-77.91%)
Mutual labels:  cryptography, crypto, libsodium
Libsodium Go
A complete overhaul of the Golang wrapper for libsodium
Stars: ✭ 105 (-79.29%)
Mutual labels:  cryptography, crypto, libsodium
Libsodium.js
libsodium compiled to Webassembly and pure JavaScript, with convenient wrappers.
Stars: ✭ 665 (+31.16%)
Mutual labels:  cryptography, crypto, libsodium
Nsec
A modern and easy-to-use cryptographic library for .NET Core based on libsodium
Stars: ✭ 217 (-57.2%)
Mutual labels:  cryptography, crypto, libsodium
libsodium-xchacha20-siv
Deterministic/nonce-reuse resistant authenticated encryption scheme using XChaCha20, implemented on libsodium.
Stars: ✭ 25 (-95.07%)
Mutual labels:  crypto, libsodium
rust-libhydrogen
Libhydrogen bindings for Rust.
Stars: ✭ 15 (-97.04%)
Mutual labels:  crypto, libsodium
WeDPR-Lab-Java-SDK
Java SDK of WeDPR-Lab-Core; WeDPR即时可用场景式隐私保护高效解决方案核心算法组件通用Java SDK
Stars: ✭ 18 (-96.45%)
Mutual labels:  cryptography, crypto
Capillary
Capillary is a library to simplify the sending of end-to-end encrypted push messages from Java-based application servers to Android clients.
Stars: ✭ 445 (-12.23%)
Mutual labels:  cryptography, crypto
Orion
Usable, easy and safe pure-Rust crypto
Stars: ✭ 227 (-55.23%)
Mutual labels:  cryptography, crypto
Privatebin
A minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES.
Stars: ✭ 3,622 (+614.4%)
Mutual labels:  cryptography, crypto
Securitydriven.inferno
✅ .NET crypto done right. Professionally audited.
Stars: ✭ 501 (-1.18%)
Mutual labels:  cryptography, crypto
Cryptopp
free C++ class library of cryptographic schemes
Stars: ✭ 3,150 (+521.3%)
Mutual labels:  cryptography, crypto
Libhydrogen
A lightweight, secure, easy-to-use crypto library suitable for constrained environments.
Stars: ✭ 247 (-51.28%)
Mutual labels:  cryptography, crypto
sodium
An wrapper for libsodium in golang
Stars: ✭ 54 (-89.35%)
Mutual labels:  crypto, libsodium
Helib
HElib is an open-source software library that implements homomorphic encryption. It supports the BGV scheme with bootstrapping and the Approximate Number CKKS scheme. HElib also includes optimizations for efficient homomorphic evaluation, focusing on effective use of ciphertext packing techniques and on the Gentry-Halevi-Smart optimizations.
Stars: ✭ 2,749 (+442.21%)
Mutual labels:  cryptography, crypto
Awesome Cryptography
A curated list of cryptography resources and links.
Stars: ✭ 3,475 (+585.4%)
Mutual labels:  cryptography, crypto
Forge
A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps
Stars: ✭ 4,204 (+729.19%)
Mutual labels:  cryptography, crypto
Swift Sodium
Safe and easy to use crypto for iOS and macOS
Stars: ✭ 400 (-21.1%)
Mutual labels:  cryptography, libsodium
S2n Tls
s2n : an implementation of the TLS/SSL protocols
Stars: ✭ 4,029 (+694.67%)
Mutual labels:  cryptography, crypto
Iotex Core
Official implementation of IoTeX blockchain protocol in Go.
Stars: ✭ 505 (-0.39%)
Mutual labels:  cryptography, crypto

libsodium-php

A simple, low-level PHP extension for libsodium.

Requires libsodium >= 1.0.9 and PHP 7.{0,1,2,3,4}.x or PHP 8.0.x

Full documentation here: Using Libsodium in PHP Projects, a guide to using the libsodium PHP extension for modern, secure, and fast cryptography.

Installation

libsodium (and, if you are using binary packages, on some distributions, libsodium-dev as well) has to be installed before this extension.

Then, use the PHP extension manager:

$ sudo pecl install -f libsodium

On some Linux distributions such as Debian, you may have to install PECL (php-pear), the PHP development package (php-dev) and a compiler (build-essential) prior to running this command.

libsodium-php 1.x compatibility API for libsodium-php 2.x

For projects using the 1.x API, or willing to use it, a compatibility layer is available.

Polyfill Libsodium brings the \Sodium\ namespace back.

Examples

Encrypt a single message using a secret key

Encryption:

$secretKey = sodium_crypto_secretbox_keygen();
$message = 'Sensitive information';

$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$encryptedMessage = sodium_crypto_secretbox($message, $nonce, $secretKey);

Decryption:

$decryptedMessage = sodium_crypto_secretbox_open($encryptedMessage, $nonce, $secretKey);

How it works:

$secret_key is a secret key. Not a password. It's binary data, not something designed to be human readable, but rather to have a key space as large as possible for a given length. The keygen() function creates such a key. That has to remain secret, as it is used both to encrypt and decrypt data.

$nonce is a unique value. Like the secret, its length is fixed. But it doesn't have to be secret, and can be sent along with the encrypted message. The nonce doesn't have to be unpredictable either. It just has to be unique for a given key. With the secretbox() API, using random_bytes() is a totally fine way to generate nonces.

Encrypted messages are slightly larger than unencrypted messages, because they include an authenticator, used by the decryption function to check that the content was not altered.

Encrypt a single message using a secret key, and hide its length

Encryption:

$secretKey = sodium_crypto_secretbox_keygen();
$message = 'Sensitive information';
$blockSize = 16;

$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$paddedMessage = sodium_pad($message, $blockSize);
$encryptedMessage = sodium_crypto_secretbox($paddedMessage, $nonce, $secretKey);

Decryption:

$decryptedPaddedMessage = sodium_crypto_secretbox_open($encryptedMessage, $nonce, $secretKey);
$decryptedMessage = sodium_unpad($decryptedPaddedMessage, $blockSize);

How it works:

Sometimes, the length of a message may provide a lot of information about its nature. If a message is one of "yes", "no" and "maybe", encrypting the message doesn't help: knowing the length is enough to know what the message is.

Padding is a technique to mitigate this, by making the length a multiple of a given block size.

Messages must be padded prior to encryption, and unpadded after decryption.

Encrypt a file using a secret key

$secretKey = sodium_crypto_secretstream_xchacha20poly1305_keygen();
$inputFile = '/tmp/example.original';
$encryptedFile = '/tmp/example.enc';
$chunkSize = 4096;

$fdIn = fopen($inputFile, 'rb');
$fdOut = fopen($encryptedFile, 'wb');

[$stream, $header] = sodium_crypto_secretstream_xchacha20poly1305_init_push($secretKey);

fwrite($fdOut, $header);

$tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE;
do {
    $chunk = fread($fdIn, $chunkSize);

    if (feof($fdIn)) {
        $tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL;
    }

    $encryptedChunk = sodium_crypto_secretstream_xchacha20poly1305_push($stream, $chunk, '', $tag);
    fwrite($fdOut, $encryptedChunk);
} while ($tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL);

fclose($fdOut);
fclose($fdIn);

Decrypt the file:

$decryptedFile = '/tmp/example.dec';

$fdIn = fopen($encryptedFile, 'rb');
$fdOut = fopen($decryptedFile, 'wb');

$header = fread($fdIn, SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES);

$stream = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $secretKey);
do {
    $chunk = fread($fdIn, $chunkSize + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES);
    [$decryptedChunk, $tag] = sodium_crypto_secretstream_xchacha20poly1305_pull($stream, $chunk);

    fwrite($fdOut, $decryptedChunk);
} while (!feof($fdIn) && $tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL);
$ok = feof($fdIn);

fclose($fdOut);
fclose($fdIn);

if (!$ok) {
    die('Invalid/corrupted input');
}

How it works:

There's a little bit more code than in the previous examples.

In fact, crypto_secretbox() would work to encrypt as file, but only if that file is pretty small. Since we have to provide the entire content as a string, it has to fit in memory.

If the file is large, we can split it into small chunks, and encrypt chunks individually.

By doing do, we can encrypt arbitrary large files. But we need to make sure that chunks cannot be deleted, truncated, duplicated and reordered. In other words, we don't have a single "message", but a stream of messages, and during the decryption process, we need a way to check that the whole stream matches what we encrypted.

So we create a new stream (init_push) and push a sequence of messages into it (push). Each individual message has a tag attached to it, by default TAG_MESSAGE. In order for the decryption process to know where the end of the stream is, we tag the last message with the TAG_FINAL tag.

When we consume the stream (init_pull, then pull for each message), we check that they can be properly decrypted, and retrieve both the decrypted chunks and the attached tags. If we read the last chunk (TAG_FINAL) and we are at the end of the file, we know that we completely recovered the original stream.

Encrypt a file using a key derived from a password:

$password = 'password';
$inputFile = '/tmp/example.original';
$encryptedFile = '/tmp/example.enc';
$chunkSize = 4096;

$alg = SODIUM_CRYPTO_PWHASH_ALG_DEFAULT;
$opsLimit = SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE;
$memLimit = SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE;
$salt = random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES);

$secretKey = sodium_crypto_pwhash(
    SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES,
    $password,
    $salt,
    $opsLimit,
    $memLimit,
    $alg
);

$fdIn = fopen($inputFile, 'rb');
$fdOut = fopen($encryptedFile, 'wb');

fwrite($fdOut, pack('C', $alg));
fwrite($fdOut, pack('P', $opsLimit));
fwrite($fdOut, pack('P', $memLimit));
fwrite($fdOut, $salt);

[$stream, $header] = sodium_crypto_secretstream_xchacha20poly1305_init_push($secretKey);

fwrite($fdOut, $header);

$tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE;
do {
    $chunk = fread($fdIn, $chunkSize);
    if (feof($fdIn)) {
        $tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL;
    }

    $encryptedChunk = sodium_crypto_secretstream_xchacha20poly1305_push($stream, $chunk, '', $tag);
    fwrite($fdOut, $encryptedChunk);
} while ($tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL);

fclose($fdOut);
fclose($fdIn);

Read the stored parameters and decrypt the file:

$decryptedFile = '/tmp/example.dec';

$fdIn = fopen($encryptedFile, 'rb');
$fdOut = fopen($decryptedFile, 'wb');

$alg = unpack('C', fread($fdIn, 1))[1];
$opsLimit = unpack('P', fread($fdIn, 8))[1];
$memLimit = unpack('P', fread($fdIn, 8))[1];
$salt = fread($fdIn, SODIUM_CRYPTO_PWHASH_SALTBYTES);

$header = fread($fdIn, SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES);

$secretKey = sodium_crypto_pwhash(
    SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES,
    $password,
    $salt,
    $opsLimit,
    $memLimit,
    $alg
);

$stream = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $secretKey);
do {
    $chunk = fread($fdIn, $chunkSize + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES);
    $res = sodium_crypto_secretstream_xchacha20poly1305_pull($stream, $chunk);

    if ($res === false) {
        break;
    }
    
    [$decrypted_chunk, $tag] = $res;
    fwrite($fdOut, $decrypted_chunk);
} while (!feof($fdIn) && $tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL);
$ok = feof($fdIn);

fclose($fdOut);
fclose($fdIn);

if (!$ok) {
    die('Invalid/corrupted input');
}

How it works:

A password cannot be directly used as a secret key. Passwords are short, must be typable on a keyboard, and people who don't use a password manager should be able to remember them.

A 8 characters password is thus way weaker than a 8 bytes key.

The sodium_crypto_pwhash() function perform a computationally intensive operation on a password in order to derive a secret key.

By doing do, brute-forcing all possible passwords in order to find the secret key used to encrypt the data becomes an expensive operation.

Multiple algorithms can be used to derive a key from a password, and for each of them, different parameters can be chosen. It is important to store all of these along with encrypted data. Using the same algorithm and the same parameters, the same secret key can be deterministically recomputed.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].