Just for fun, let's encrypt some stuff in client-side JavaScript and have a PHP server decrypt it. Note that this will never replace TLS (HTTPS).
You'll want the latest release of sodium-plus for this. (As of this writing, it's version 0.4.0.)
<script
src="/static/js/sodium-plus.min.js"
integrity="sha384-lv7SVE0eb0bXA3fgK6PwlhViiUwG6tBuMAhS8XX7RvBvyRcdEdJ8HKtFgs4vHTUh"
></script>
Next, you'll want to write some JavaScript code to encrypt a message and send it to a server. I'll be using jQuery for this example, but you can easily adapt it to use a XMLHttpRequest
object instead.
Let's define two functions. One loads a CryptographyKey
object from a hard-coded string (n.b. you never want to actually do this, but for the sake of an easy, working example, we're using a hard-coded secret). The other actually encrypts a message.
/**
* Get the example key. In the real world, you want to generate these randomly.
*/
async function getExampleKey() {
if (!window.sodium) window.sodium = await SodiumPlus.auto();
return CryptographyKey.from(
'e9897cea109576c2f8088c277125d553e4f83afbc0abbb92cfb1f7b776b4fee0',
'hex'
);
// return await sodium.crypto_secretbox_keygen();
}
/**
* Encrypt a message under a given key.
*/
async function encryptMessage(message, key) {
if (!window.sodium) window.sodium = await SodiumPlus.auto();
let nonce = await sodium.randombytes_buf(24);
let encrypted = await sodium.crypto_secretbox(message, nonce, key);
return nonce.toString('hex') + encrypted.toString('hex');
}
Next, you'll want to write a function that gathers user input, encrypts it, and sends it to a server.
async function sendEncryptedMessage() {
let key = await getExampleKey();
let message = $("#user-input").val();
let encrypted = await encryptMessage(message, key);
$.post("/send-message", {"message": encrypted}, function (response) {
console.log(response);
$("#output").append("<li><pre>" + response.message + "</pre></li>");
});
}
...and some supporting HTML:
<label for="user-input">Type a message to encrypt and send:</label>
<textarea id="user-input"></textarea>
<button id="send-it" type="button">Send Encrypted Message</button>
<hr />
<ol id="output"></ol>
<script type="text/javascript">
$("#send-it").on('click', sendEncryptedMessage);
</script>
You're going to want paragonie/sodium_compat.
If you're using PHP 7.2, with overwhelming probability you can just use the built in sodium_*
functions. However, some distros may incorrectly disable the sodium extension by default. So to play it safe, install sodium_compat anyway.
If you're using a framework (Symfony, Laravel), your code will look a lot cleaner, but for the sake of illustration, the decryption code will look like this:
<?php
declare(strict_types=1);
require 'vendor/autoload.php'; // Composer
header('Content-Type: application/json');
$key = sodium_hex2bin('e9897cea109576c2f8088c277125d553e4f83afbc0abbb92cfb1f7b776b4fee0');
$encrypted = $_POST['message'] ?? null;
if (!$encrypted) {
echo json_encode(
['message' => null, 'error' => 'no message provided'],
JSON_PRETTY_PRINT
);
exit(1);
}
$nonce = sodium_hex2bin(substr($encrypted, 0, 48));
$ciphertext = sodium_hex2bin(substr($encrypted, 48));
$plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
echo json_encode(
['message' => $plaintext, 'original' => $encrypted],
JSON_PRETTY_PRINT
);
When you type in a message and press the button, it will encrypt it and send a hex-encoded string to the server.
The PHP code will then decrypt the message and return the plaintext in a JSON response.
The JavaScript code will then grab the plaintext from the JSON response and append it to the output field below the form.
This is just a toy example to illustrate how to use sodium-plus (JavaScript) and libsodium (PHP) to encrypt/decrypt messages.
We took a lot of shortcuts that you won't want to take in a real system (for example: hard-coding the encryption keys, and eschewing error-checking in favor of brevity).
If you'd like to do something more advanced (public-key encryption in JavaScript and the congruent PHP functions), the documentation is available for free online.
Shameless plug: If you're looking for security experts to review your JavaScript or PHP code, check out why you may want to hire Paragon Initiative Enterprises for code audits.