co-stack / reversible-halite
Provides portable reversible encryption functions based on paragonie/halite, an advanced security library
Requires
- php: ^7.2 || ^8.0 <8.4
- ext-sodium: *
- co-stack/reversible: ^v1.7.0
- paragonie/halite: ^v4.8.0
Requires (Dev)
- infection/infection: ^0.25.3
- phpunit/phpunit: ^9.5
README
What is a reversible function?
Please see co-stack/reversible for more information about reversibles.
About
This package is an extension to co-stack/reversible. It contains several reversibles for Encryption/Decryption and Signing/Verifying messages. All reversibles in this package are based on paragonie/halite, a "High-level cryptography interface powered by libsodium".
Examples
Simple hybrid encryption
- Encode and send the message
$localPrivateKey = \ParagonIE\Halite\KeyFactory::loadEncryptionSecretKey('/path/to/local/private.key');
$foreignPublicKey = \ParagonIE\Halite\KeyFactory::loadEncryptionPublicKey('/path/to/foreign/key.pub');
$superSecretMessage = 'Foo bar baz! Beng? Baz baz. Bada boom. Multipass!';
$reversible = new \CoStack\ReversibleHalite\Operation\Encryption\AuthenticatedAsymmetricEncryption(
$localPrivateKey->getRawKeyMaterial(),
$foreignPublicKey->getRawKeyMaterial()
);
$encryptedMessage = $reversible->execute($superSecretMessage);
// Send the $encryptedMessage to the receiver. You can send this per HTTP or Telnet, it is securely encrypted with the
// receivers public key and authenticated by your private key.
send($encryptedMessage);
- Receive and decrypt the message
$encryptedMessage = receive();
$localPrivateKey = \ParagonIE\Halite\KeyFactory::loadEncryptionSecretKey('/path/to/foreign/private.key');
$foreignPublicKey = \ParagonIE\Halite\KeyFactory::loadEncryptionPublicKey('/path/to/local/key.pub');
$reversible = new \CoStack\ReversibleHalite\Operation\Encryption\AuthenticatedAsymmetricEncryption(
$localPrivateKey->getRawKeyMaterial(),
$foreignPublicKey->getRawKeyMaterial()
);
try {
$superSecretMessage = $reversible->reverse($encryptedMessage);
} catch (\CoStack\Reversible\Exception\DecryptionFailedException $exception) {
echo 'The message was altered or was not sent by a trusted source!';
exit(1);
}
Wait. The example says "hybrid encryption", but the code uses AuthenticatedAsymmetricEncryption
?
Yes, this is correct. Asymmetric encryption has some drawbacks, like the maximum length of the encrypted information and
its very slow execution. To bypass these limitations, halite generates a shared secret key based on the encryption and
decryption keys. Then, the shared secret key is used to encrypt the message with high performance.
In a pipe
The true power of co-stack/reversible lies in its portability and chaining of functions. You can compose a set of functions into a pipe, which can be executed and reversed like it would be a single reversible.
$signingPrivateKey = \ParagonIE\Halite\KeyFactory::loadEncryptionSecretKey('/path/to/local/private.key');
$encryptionPublicKey = \ParagonIE\Halite\KeyFactory::loadEncryptionPublicKey('/path/to/foreign/key.pub');
$pipe = new \CoStack\Reversible\Applicable\ReversiblePipe();
$pipe->enqueue(new \CoStack\ReversibleHalite\Operation\Encryption\SignedAsymmetricEncryption($signingPrivateKey, $encryptionPublicKey));
$pipe->enqueue(new \CoStack\Reversible\Operation\Compression\GzipCompression());
$pipe->enqueue(new \CoStack\Reversible\Operation\Encoding\UrlEncode());
$myValue = 'foo bar baz';
$secretEncodedEncryptedSigned = $pipe->execute($myValue);
// Transfer
$decryptionPrivateKey = \ParagonIE\Halite\KeyFactory::loadEncryptionSecretKey('/path/to/foreign/private.key');
$validationPublicKey = \ParagonIE\Halite\KeyFactory::loadEncryptionPublicKey('/path/to/local/key.pub');
$pipe = new \CoStack\Reversible\Applicable\ReversiblePipe();
$pipe->enqueue(new \CoStack\ReversibleHalite\Operation\Encryption\SignedAsymmetricEncryption($decryptionPrivateKey, $validationPublicKey));
$pipe->enqueue(new \CoStack\Reversible\Operation\Compression\GzipCompression());
$pipe->enqueue(new \CoStack\Reversible\Operation\Encoding\UrlEncode());
try {
$myOriginalValue = $pipe->reverse($secretEncodedEncryptedSigned);
} catch (\Throwable $exception) {
echo 'The message was altered or was not sent by a trusted source!';
exit(1);
}
$myValue === $myOriginalValue; // true