aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2024-03-15 11:30:28 +0000
committerMario <mario@mariovavti.com>2024-03-15 11:30:28 +0000
commitdddcddc453bdbd59e1cafcb8ca8aeb2225dfda9d (patch)
tree2232fb9df1bbcfee9a76c85db67c9a4045d64a84
parent754d90a676e6cd8166965f12f2b3fa0bb203988e (diff)
downloadvolse-hubzilla-dddcddc453bdbd59e1cafcb8ca8aeb2225dfda9d.tar.gz
volse-hubzilla-dddcddc453bdbd59e1cafcb8ca8aeb2225dfda9d.tar.bz2
volse-hubzilla-dddcddc453bdbd59e1cafcb8ca8aeb2225dfda9d.zip
refactor sodium b2b encryption
-rw-r--r--include/bbcode.php40
-rw-r--r--view/js/crypto.js38
2 files changed, 48 insertions, 30 deletions
diff --git a/include/bbcode.php b/include/bbcode.php
index b39822b05..20a866073 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -246,38 +246,45 @@ function bb_replace_images($body, $images) {
function bb_parse_crypt($match) {
$matches = [];
- $attributes = $match[1];
$hint = '';
$algorithm = '';
+ $payload = $match[1];
+
+ if (isset($match[2])) {
+ // backwards compatibility
- preg_match("/alg='(.*?)'/ism", $attributes, $matches);
- $algorithm = $matches[1] ?? '';
+ $attributes = $match[1];
+ $payload = $match[2];
- if (!$algorithm) {
- preg_match("/alg=\&quot\;(.*?)\&quot\;/ism", $attributes, $matches);
+ preg_match("/alg='(.*?)'/ism", $attributes, $matches);
$algorithm = $matches[1] ?? '';
- }
- preg_match("/hint='(.*?)'/ism", $attributes, $matches);
- $hint = $matches[1] ?? '';
+ if (!$algorithm) {
+ preg_match("/alg=\&quot\;(.*?)\&quot\;/ism", $attributes, $matches);
+ $algorithm = $matches[1] ?? '';
+ }
- if (!$hint) {
- preg_match("/hint=\&quot\;(.*?)\&quot\;/ism", $attributes, $matches);
+ preg_match("/hint='(.*?)'/ism", $attributes, $matches);
$hint = $matches[1] ?? '';
+
+ if (!$hint) {
+ preg_match("/hint=\&quot\;(.*?)\&quot\;/ism", $attributes, $matches);
+ $hint = $matches[1] ?? '';
+ }
}
- $x = random_string();
+ $x = random_string(32);
- $f = 'sodium_decrypt';
+ $onclick = 'onclick="sodium_decrypt(\'' . $payload . '\',\'#' . $x . '\');"';
if (in_array($algorithm, ['AES-128-CCM', 'rot13', 'triple-rot13'])) {
- $f = 'hz_decrypt'; // deprecated
+ // backwards compatibility
+ $onclick = 'onclick="hz_decrypt(\'' . $algorithm . '\',\'' . $hint . '\',\'' . $payload . '\',\'#' . $x . '\');"';
}
- $onclick = 'onclick="' . $f . '(\'' . $algorithm . '\',\'' . $hint . '\',\'' . $match[2] . '\',\'#' . $x . '\');"';
$label = t('Encrypted content');
- $text = '<br /><div id="' . $x . '"><img class="cursor-pointer" src="' . z_root() . '/images/lock_icon.svg" ' . $onclick . ' alt="' . $label . '" title="' . $label . '" /></div><br />';
+ $text = '<div id="' . $x . '" class="encrypted-content"><img class="cursor-pointer" src="' . z_root() . '/images/lock_icon.svg" ' . $onclick . ' alt="' . $label . '" title="' . $label . '" /></div>';
return $text;
}
@@ -1627,8 +1634,7 @@ function bbcode($text, $options = []) {
// crypt
if (strpos($text,'[/crypt]') !== false) {
- $x = random_string();
- $text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism",'<br /><div id="' . $x . '"><img class="cursor-pointer" src="' .z_root() . '/images/lock_icon.svg" onclick="red_decrypt(\'rot13\',\'\',\'$1\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /><br /></div>', $text);
+ $text = preg_replace_callback("/\[crypt\](.*?)\[\/crypt\]/ism", 'bb_parse_crypt', $text);
$text = preg_replace_callback("/\[crypt (.*?)\](.*?)\[\/crypt\]/ism", 'bb_parse_crypt', $text);
}
diff --git a/view/js/crypto.js b/view/js/crypto.js
index 55b9aea11..bc399caa3 100644
--- a/view/js/crypto.js
+++ b/view/js/crypto.js
@@ -25,6 +25,11 @@ async function sodium_encrypt(element) {
}
let message = $(element).val();
+
+ if (!message) {
+ return false;
+ }
+
let password = prompt(aStr['passphrase']);
if (!password) {
@@ -35,6 +40,7 @@ async function sodium_encrypt(element) {
let salt = await sodium.randombytes_buf(16);
let nonce = await sodium.randombytes_buf(24);
+
let key = await sodium.crypto_pwhash(
32,
password,
@@ -47,31 +53,37 @@ async function sodium_encrypt(element) {
let ciphertext = await sodium.crypto_secretbox(message, nonce, key);
delete message, password, key;
- let s = await sodium.sodium_bin2hex(salt);
- let n = await sodium.sodium_bin2hex(nonce);
- let c = await sodium.sodium_bin2hex(ciphertext);
- let encrypted = window.btoa(s + '.' + n + '.' + c);
- let val = "[crypt alg='XSalsa20' hint='" + hint + "']" + encrypted + '[/crypt]';
+ let payload = {
+ hint: hint,
+ alg: 'XSalsa20',
+ salt: await sodium.sodium_bin2hex(salt),
+ nonce: await sodium.sodium_bin2hex(nonce),
+ ciphertext: await sodium.sodium_bin2hex(ciphertext)
+ };
+
+ let val = "[crypt]" + window.btoa(JSON.stringify(payload)) + '[/crypt]';
$(element).val(val);
}
-async function sodium_decrypt(alg, hint, encrypted, element) {
- if (alg !== 'XSalsa20') {
+async function sodium_decrypt(payload, element) {
+ let arr = JSON.parse(window.atob(payload));
+
+ if (arr.alg !== 'XSalsa20') {
alert('Unsupported algorithm');
return false;
}
- let arr = window.atob(encrypted).split('.');
- let salt = await sodium.sodium_hex2bin(arr[0]);
- let nonce = await sodium.sodium_hex2bin(arr[1]);
- let ciphertext = await sodium.sodium_hex2bin(arr[2]);
- let password = prompt((hint.length) ? hex2bin(hint) : aStr['passphrase']);
+ let password = prompt((arr.hint.length) ? hex2bin(arr.hint) : aStr['passphrase']);
if (!password) {
return false;
}
+ let salt = await sodium.sodium_hex2bin(arr.salt);
+ let nonce = await sodium.sodium_hex2bin(arr.nonce);
+ let ciphertext = await sodium.sodium_hex2bin(arr.ciphertext);
+
let key = await sodium.crypto_pwhash(
32,
password,
@@ -84,7 +96,7 @@ async function sodium_decrypt(alg, hint, encrypted, element) {
delete password, key;
if ($(element).css('display') === 'none' && typeof tinyMCE !== typeof undefined) {
- tinyMCE.activeEditor.setContent(newdiv);
+ tinyMCE.activeEditor.setContent(decrypted.toString('utf-8'));
}
else {
$(element).html(decrypted.toString('utf-8'));