密码学 - Salt 和 WASM

本文介绍了如何使用libsodium.js在WebAssembly (WASM) 中实现对称密钥加密。libsodium是一个加密库,它选择最佳的对称加密方法(如AES和XChaCha20),并通过WASM在浏览器中快速执行。文章提供了代码示例,展示了如何使用libsodium.js进行加密和解密操作,以及如何在实际应用中使用。

Salt 和 WASM

由于网络安全的核心是对称密钥加密。通过这种方式,我们使用相同的加密密钥进行加密和解密:

不过,现在我们在密码处理过程中添加了一个 nonce 值,并且还可以添加加密和解密过程所需的额外数据:

但是有这么多种类型的对称密钥方法(AES、ChaCha20、3DES、RC4 等)和模式(ECB、CBC、GCM 等),那么你应该选择哪一种才能获得最佳实践?好吧,libsodium 库选择了可用的最佳方法并使用它们。为此,我们有 128 位 AES、256 位 AES 和 XChaCha20。这些都使用额外的数据来增强加密过程的安全性,并且易于使用 [ here]。

WASM 和 libsodium

WebAssembly (WASM) 能够在浏览器中快速执行代码,代码几乎以原生方式在客户端机器上运行。它本质上也很紧凑,几乎可以在所有类型的硬件和几乎每个浏览器中运行。它也是安全的,代码在其自己的沙盒区域内运行。因此,我们可以使用 libsodium.js 来实现对称密钥加密,使用 C++ sodium 代码的编译版本。

libsodium.js 是一个 sodium 加密库,它被编译为 WASM (WebAssembly),并使用与 Python 端口相同的 sodium 方法。总的来说,libsodium 使用 128 位 AES、256 位 AES 或 XChaCha20。这样,我们有一个用于 128 位 AES 的 128 位密钥,以及一个用于 256 位 AES 和 XChaCha20 的 256 位密钥。对于 128 位 AES,我们有一个 128 位的 nonce 值,对于 256 位 AES,我们有一个 256 位的 nonce。对于 XChaCha20,我们有一个 192 位的 nonce。在下文中,我们将选择加密类型,并生成一个随机的 nonce 值和 128 字节的附加数据 (AD)。这种类型的密码被称为 AEAD(带有附加数据的认证加密)。

要实现 128 位 AES,可以使用以下方法生成密钥、nonce 和附加数据:

key = await window.sodium.crypto_aead_aegis128l_keygen();
nonce = await window.sodium.randombytes_buf(window.sodium.crypto_aead_aegis128l_NPUBBYTES);

const ad = await window.sodium.randombytes_buf(64);

然后我们可以加密一条消息 (msg) 并使用以下方法解密密文:

ciphertext = await window.sodium.crypto_aead_aegis128l_encrypt(msg, ad, null, nonce, key);
decrypted = await window.sodium.crypto_aead_aegis128l_decrypt(null, ciphertext, ad, nonce, key);

完整的代码集成在 [ here]:

<script src="/js/sodium.js" async></script>

<script type="module">

    window.sodium = {
        onload: function (sodium) {
            function toHex(buffer) {
                return Array.prototype.map.call(buffer, x => ('00' + x.toString(16)).slice(-2)).join('');
            }

            const message = document.getElementById("message").value;
            var msg = window.sodium.from_string(message);

            var ciphertext;
            var decrypted;
            var key;
            var nonce;

            key = window.sodium.crypto_aead_aegis128l_keygen();
            document.getElementById('key').innerText = toHex(key) + "\n";
            nonce = window.sodium.randombytes_buf(window.sodium.crypto_aead_aegis128l_NPUBBYTES);
            document.getElementById('nonce').innerText = toHex(nonce) + "\n";

            const ad = window.sodium.randombytes_buf(64);
            document.getElementById('ad').innerText = toHex(ad) + "\n";

            ciphertext = window.sodium.crypto_aead_aegis128l_encrypt(msg, ad, null, nonce, key);
            decrypted = window.sodium.crypto_aead_aegis128l_decrypt(null, ciphertext, ad, nonce, key);

            document.getElementById('Ciphertext').innerText = toHex(ciphertext);
            document.getElementById('Decrypted').innerText = new TextDecoder().decode(decrypted);
        }
    };

    (async function () {

        async function update() {

            function toHex(buffer) {
                return Array.prototype.map.call(buffer, x => ('00' + x.toString(16)).slice(-2)).join('');
            }
            await window.sodium.ready;

            const message = document.getElementById("message").value;
            var msg = await window.sodium.from_string(message);

            var ciphertext;
            var decrypted;
            var key;
            var nonce;

            if (document.getElementById('size').value == "1") {

                key = await window.sodium.crypto_aead_aegis128l_keygen();
                document.getElementById('key').innerText = toHex(key) + "\n";
                nonce = await window.sodium.randombytes_buf(window.sodium.crypto_aead_aegis128l_NPUBBYTES);
                document.getElementById('nonce').innerText = toHex(nonce) + "\n";

                const ad = await window.sodium.randombytes_buf(64);
                document.getElementById('ad').innerText = toHex(ad) + "\n";

                ciphertext = await window.sodium.crypto_aead_aegis128l_encrypt(msg, ad, null, nonce, key);
                decrypted = await window.sodium.crypto_aead_aegis128l_decrypt(null, ciphertext, ad, nonce, key);
            } else if (document.getElementById('size').value == "2") {

                key = window.sodium.crypto_aead_aegis256_keygen();
                document.getElementById('key').innerText = toHex(key) + "\n";
                nonce = window.sodium.randombytes_buf(window.sodium.crypto_aead_aegis256_NPUBBYTES);
                document.getElementById('nonce').innerText = toHex(nonce) + "\n";

                const ad = window.sodium.randombytes_buf(64);
                document.getElementById('ad').innerText = toHex(ad) + "\n";

                ciphertext = sodium.crypto_aead_aegis256_encrypt(msg, ad, null, nonce, key);
                decrypted = sodium.crypto_aead_aegis256_decrypt(null, ciphertext, ad, nonce, key);

            } else {
                key = window.sodium.crypto_aead_aegis256_keygen();
                document.getElementById('key').innerText = toHex(key) + "\n";
                nonce = window.sodium.randombytes_buf(24);
                document.getElementById('nonce').innerText = toHex(nonce) + "\n";

                const ad = window.sodium.randombytes_buf(64);
                document.getElementById('ad').innerText = toHex(ad) + "\n";

                ciphertext = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(msg, ad, null, nonce, key);
                decrypted = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(null, ciphertext, ad, nonce, key);

            }

            document.getElementById('Ciphertext').innerText = toHex(ciphertext);
            document.getElementById('Decrypted').innerText = new TextDecoder().decode(decrypted);

        }

        update();
        document.getElementById("message").addEventListener("input", update);
        document.getElementById("message").innerText = "Hello";
        document.getElementById("genkey").addEventListener("click", update);
        document.getElementById("size").addEventListener("click", update);

    })();

</script>

以下是一个示例 [ here]:

你可以在这里尝试一下:

使用 JavaScript 在 WASM 中使用 libsodium.js 的 AES 加密 \ \ libsodium.js 是一个 sodium 加密库,它被编译为 WASM (WebAssembly),并使用与…相同的 sodium 方法\ \ asecuritysite.com

  • 原文链接: medium.com/asecuritysite...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
asecuritysite
asecuritysite
江湖只有他的大名,没有他的介绍。