diff options
author | Mario <mario@mariovavti.com> | 2024-03-10 22:35:59 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2024-03-10 22:35:59 +0000 |
commit | ee8aba3221f995b265c3196505a1c7c26b76f116 (patch) | |
tree | 2b32c6153b40da13d7ebd944fe8e7fd383785f32 | |
parent | 0a730935f52ae33bf6132a1ae522e88a37b0f5e6 (diff) | |
download | volse-hubzilla-ee8aba3221f995b265c3196505a1c7c26b76f116.tar.gz volse-hubzilla-ee8aba3221f995b265c3196505a1c7c26b76f116.tar.bz2 volse-hubzilla-ee8aba3221f995b265c3196505a1c7c26b76f116.zip |
implement sodium-plus library to replace unmaintained sjcl
-rw-r--r-- | include/bbcode.php | 38 | ||||
-rw-r--r-- | view/js/crypto.js | 86 | ||||
-rw-r--r-- | view/php/theme_init.php | 1 | ||||
-rw-r--r-- | view/tpl/chat.tpl | 4 | ||||
-rw-r--r-- | view/tpl/comment_item.tpl | 2 | ||||
-rw-r--r-- | view/tpl/jot.tpl | 2 |
6 files changed, 104 insertions, 29 deletions
diff --git a/include/bbcode.php b/include/bbcode.php index 848d117fb..b39822b05 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -247,41 +247,39 @@ function bb_parse_crypt($match) { $matches = []; $attributes = $match[1]; - - $algorithm = ""; + $hint = ''; + $algorithm = ''; preg_match("/alg='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $algorithm = $matches[1]; - - preg_match("/alg=\"\;(.*?)\"\;/ism", $attributes, $matches); - if ($matches[1] != "") - $algorithm = $matches[1]; + $algorithm = $matches[1] ?? ''; - $hint = ""; + if (!$algorithm) { + preg_match("/alg=\"\;(.*?)\"\;/ism", $attributes, $matches); + $algorithm = $matches[1] ?? ''; + } preg_match("/hint='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $hint = $matches[1]; - preg_match("/hint=\"\;(.*?)\"\;/ism", $attributes, $matches); - if ($matches[1] != "") - $hint = $matches[1]; + $hint = $matches[1] ?? ''; + + if (!$hint) { + preg_match("/hint=\"\;(.*?)\"\;/ism", $attributes, $matches); + $hint = $matches[1] ?? ''; + } $x = random_string(); - $f = 'hz_decrypt'; + $f = 'sodium_decrypt'; - //legacy cryptojs support - if(plugin_is_installed('cryptojs')) { - $f = ((in_array($algorithm, ['AES-128-CCM', 'rot13', 'triple-rot13'])) ? 'hz_decrypt' : 'red_decrypt'); + if (in_array($algorithm, ['AES-128-CCM', 'rot13', 'triple-rot13'])) { + $f = 'hz_decrypt'; // deprecated } $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 = '<br /><div id="' . $x . '"><img class="cursor-pointer" src="' . z_root() . '/images/lock_icon.svg" ' . $onclick . ' alt="' . $label . '" title="' . $label . '" /></div><br />'; - return $Text; + return $text; } /** diff --git a/view/js/crypto.js b/view/js/crypto.js index 14bc1e0a2..55b9aea11 100644 --- a/view/js/crypto.js +++ b/view/js/crypto.js @@ -15,6 +15,82 @@ function str_rot13 (str) { }); } +async function sodium_encrypt(element) { + if (!window.sodium) { + window.sodium = await SodiumPlus.auto(); + } + + if (typeof tinyMCE !== typeof undefined) { + tinyMCE.triggerSave(false,true); + } + + let message = $(element).val(); + let password = prompt(aStr['passphrase']); + + if (!password) { + return false; + } + + let hint = bin2hex(prompt(aStr['passhint'])); + + let salt = await sodium.randombytes_buf(16); + let nonce = await sodium.randombytes_buf(24); + let key = await sodium.crypto_pwhash( + 32, + password, + salt, + sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE + ); + + // Message can be a string, buffer, array, etc. + 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]'; + + $(element).val(val); +} + +async function sodium_decrypt(alg, hint, encrypted, element) { + if (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']); + + if (!password) { + return false; + } + + let key = await sodium.crypto_pwhash( + 32, + password, + salt, + sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE + ); + + let decrypted = await sodium.crypto_secretbox_open(ciphertext, nonce, key); + delete password, key; + + if ($(element).css('display') === 'none' && typeof tinyMCE !== typeof undefined) { + tinyMCE.activeEditor.setContent(newdiv); + } + else { + $(element).html(decrypted.toString('utf-8')); + } +} + function hz_encrypt(alg, elem) { var enc_text = ''; var newdiv = ''; @@ -33,7 +109,7 @@ function hz_encrypt(alg, elem) { var enc_key = bin2hex(passphrase); // If you don't provide a key you get rot13, which doesn't need a key - // but consequently isn't secure. + // but consequently isn't secure. if(! enc_key) alg = 'rot13'; @@ -44,7 +120,7 @@ function hz_encrypt(alg, elem) { if(alg == 'AES-128-CCM') { // This is the prompt we're going to use when the receiver tries to open it. - // Maybe "Grandma's maiden name" or "our secret place" or something. + // Maybe "Grandma's maiden name" or "our secret place" or something. var enc_hint = bin2hex(prompt(aStr['passhint'])); @@ -62,7 +138,7 @@ function hz_encrypt(alg, elem) { // property of our source element - because a tinymce instance // will have display "none". If a normal textarea such as in a comment // box has display "none" you wouldn't be able to type in it. - + if($(elem).css('display') == 'none' && typeof tinyMCE !== "undefined") { tinyMCE.activeEditor.setContent(newdiv); } @@ -98,8 +174,8 @@ function hz_decrypt(alg, hint, text, elem) { enc_key = ''; // Not sure whether to drop this back in the conversation display. - // It probably needs a lightbox or popup window because any conversation - // updates could + // It probably needs a lightbox or popup window because any conversation + // updates could // wipe out the text and make you re-enter the key if it was in the // conversation. For now we do that so you can read it. diff --git a/view/php/theme_init.php b/view/php/theme_init.php index b08651689..50da8b5f9 100644 --- a/view/php/theme_init.php +++ b/view/php/theme_init.php @@ -26,6 +26,7 @@ head_add_js('/library/readmore.js/readmore.js'); head_add_js('/library/jgrowl/jquery.jgrowl.min.js'); head_add_js('/library/sjcl/sjcl.js'); +head_add_js('/library/sodium-plus/dist/sodium-plus.min.js'); head_add_js('acl.js'); head_add_js('webtoolkit.base64.js'); diff --git a/view/tpl/chat.tpl b/view/tpl/chat.tpl index da8da30f2..a0e528894 100644 --- a/view/tpl/chat.tpl +++ b/view/tpl/chat.tpl @@ -70,7 +70,7 @@ </div> {{if $feature_encrypt}} <div class="btn-group me-2 d-none d-md-flex"> - <button id="chat-encrypt-wrapper" class="btn btn-outline-secondary btn-sm" onclick="hz_encrypt('{{$cipher}}', '#chatText'); return false;"> + <button id="chat-encrypt-wrapper" class="btn btn-outline-secondary btn-sm" onclick="sodium_encrypt('#chatText'); return false;"> <i id="chat-encrypt" class="fa fa-key jot-icons" title="{{$encrypt}}" ></i> </button> </div> @@ -83,7 +83,7 @@ <a class="dropdown-item" href="#" onclick="chatJotGetLink(); return false;" ><i class="fa fa-link"></i> {{$insert}}</a> {{if $feature_encrypt}} <div class="dropdown-divider"></div> - <a class="dropdown-item" href="#" onclick="hz_encrypt('{{$cipher}}', '#chatText'); return false;"><i class="fa fa-key"></i> {{$encrypt}}</a> + <a class="dropdown-item" href="#" onclick="sodium_encrypt('#chatText'); return false;"><i class="fa fa-key"></i> {{$encrypt}}</a> {{/if}} </div> </div> diff --git a/view/tpl/comment_item.tpl b/view/tpl/comment_item.tpl index d29193901..891d901c9 100644 --- a/view/tpl/comment_item.tpl +++ b/view/tpl/comment_item.tpl @@ -50,7 +50,7 @@ </div> {{if $feature_encrypt}} <div class="btn-group me-2"> - <button class="btn btn-outline-secondary btn-sm border-0" title="{{$encrypt}}" onclick="hz_encrypt('{{$cipher}}','#comment-edit-text-' + '{{$id}}'); return false;"> + <button class="btn btn-outline-secondary btn-sm border-0" title="{{$encrypt}}" onclick="sodium_encrypt('#comment-edit-text-' + '{{$id}}'); return false;"> <i class="fa fa-key comment-icon"></i> </button> </div> diff --git a/view/tpl/jot.tpl b/view/tpl/jot.tpl index 0ffdc0517..eedd92170 100644 --- a/view/tpl/jot.tpl +++ b/view/tpl/jot.tpl @@ -160,7 +160,7 @@ </button> {{/if}} {{if $feature_encrypt}} - <button type="button" id="profile-encrypt-wrapper" class="btn btn-outline-secondary btn-sm border-0" title="{{$encrypt}}" onclick="hz_encrypt('{{$cipher}}','#profile-jot-text');return false;"> + <button type="button" id="profile-encrypt-wrapper" class="btn btn-outline-secondary btn-sm border-0" title="{{$encrypt}}" onclick="sodium_encrypt('#profile-jot-text'); return false;"> <i id="profile-encrypt" class="fa fa-key jot-icons"></i> </button> {{/if}} |