本文介绍了如何使用libsodium.js在WebAssembly (WASM) 中实现对称密钥加密。libsodium是一个加密库,它选择最佳的对称加密方法(如AES和XChaCha20),并通过WASM在浏览器中快速执行。文章提供了代码示例,展示了如何使用libsodium.js进行加密和解密操作,以及如何在实际应用中使用。
由于网络安全的核心是对称密钥加密。通过这种方式,我们使用相同的加密密钥进行加密和解密:
不过,现在我们在密码处理过程中添加了一个 nonce 值,并且还可以添加加密和解密过程所需的额外数据:
但是有这么多种类型的对称密钥方法(AES、ChaCha20、3DES、RC4 等)和模式(ECB、CBC、GCM 等),那么你应该选择哪一种才能获得最佳实践?好吧,libsodium 库选择了可用的最佳方法并使用它们。为此,我们有 128 位 AES、256 位 AES 和 XChaCha20。这些都使用额外的数据来增强加密过程的安全性,并且易于使用 [ here]。
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]:
你可以在这里尝试一下:
- 原文链接: medium.com/asecuritysite...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!