我对构建一个个人使用的小型应用程序感兴趣,该应用程序将使用JavaScript在客户端加密和解密信息。加密的信息将存储在服务器上的数据库中,但绝不会存储解密的版本。

它不必是超级duper安全,但我想使用目前未被破坏的算法。

理想情况下,我可以做一些

var gibberish = encrypt(string, salt, key);

来生成编码的字符串,诸如此类

var sensical = decrypt(gibberish, key);

稍后再解码。

到目前为止,我看到的是: http://bitwiseshiftleft.github.io/sjcl/

我还应该看看其他的图书馆吗?


当前回答

现有的利用SJCL、CryptoJS和/或WebCrypto的答案不一定是错误的,但它们并不像你最初怀疑的那样安全。通常你要用libsodium。首先我将解释为什么,然后如何。

为什么不是SJCL, CryptoJS, WebCrypto等?

简单的回答:为了让你的加密实际上是安全的,这些库希望你做出太多的选择,例如分组密码模式(CBC, CTR, GCM;如果你不知道我列出的三种方法中哪一种是安全的,在什么限制下使用,你根本不应该被这种选择所困扰)。

除非你的职位是密码学工程师,否则你很难安全地实现它。

为什么要避免使用CryptoJS?

CryptoJS提供了一些构建块,并希望您知道如何安全地使用它们。它甚至默认为CBC模式(存档)。

为什么CBC模式不好?

阅读这篇关于AES-CBC漏洞的文章。

为什么要避免WebCrypto?

WebCrypto是一种家常便饭的标准,由委员会设计,目的与密码学工程正交。具体来说,WebCrypto旨在取代Flash,而不是提供安全性。

为什么要避免SJCL?

SJCL的公共API和文档要求用户使用人类记住的密码加密数据。这几乎不是你在现实世界中想要做的事情。

此外:它的默认PBKDF2轮计数大约是您想要的86倍。AES-128-CCM可能没问题。

在上述三种选择中,SJCL是最不可能以悲剧收场的。但也有更好的选择。

为什么利布纳更好?

您不需要在密码模式、散列函数和其他不必要的选项之间进行选择。您永远不会冒险搞砸参数并从协议中移除所有安全性。

相反,libsodium只是为您提供了一些简单的选项,以实现最大的安全性和最少的api。

Crypto_box () / crypto_box_open()提供经过身份验证的公钥加密。 所讨论的算法结合了X25519 (ECDH over Curve25519)和XSalsa20-Poly1305,但是您不需要知道(甚至不需要关心)就可以安全地使用它 Crypto_secretbox () / crypto_secretbox_open()提供共享密钥认证加密。 这里讨论的算法是XSalsa20-Poly1305,但您不需要知道/关心

此外,libsodium在许多流行的编程语言中都有绑定,因此很可能只有在尝试与另一种编程堆栈进行互操作时,libsodium才能工作。而且,libsodium的速度非常快,而且不会牺牲安全性。

如何在JavaScript中使用Libsodium ?

首先,你需要决定一件事:

您只是想加密/解密数据(可能仍然以某种方式在数据库查询中安全地使用明文),而不担心细节吗?还是…… 您是否需要实现特定的协议?

如果您选择了第一个选项,请获取CipherSweet.js。

相关文档可以在网上找到。EncryptedField对于大多数用例来说已经足够了,但是如果有很多不同的字段需要加密,那么EncryptedRow和EncryptedMultiRows api可能会更容易一些。

有了CipherSweet,你甚至不需要知道什么是nonce/IV就可以安全地使用它。

此外,它处理int/float加密,而不会通过密文大小泄露有关内容的事实。

否则,您将需要钠加,这是一个用户友好的前端,以各种libsodium包装。Sodium-Plus允许您编写易于审核和推理的高性能、异步、跨平台代码。

要安装钠加,只需运行…

npm install sodium-plus

目前没有浏览器支持的公共CDN。这种情况很快就会改变。但是,如果你需要的话,你可以从最新的Github版本中获取sodium-plus.min.js。

const { SodiumPlus } = require('sodium-plus'); let sodium; (async function () { if (!sodium) sodium = await SodiumPlus.auto(); let plaintext = 'Your message goes here'; let key = await sodium.crypto_secretbox_keygen(); let nonce = await sodium.randombytes_buf(24); let ciphertext = await sodium.crypto_secretbox( plaintext, nonce, key ); console.log(ciphertext.toString('hex')); let decrypted = await sodium.crypto_secretbox_open( ciphertext, nonce, key ); console.log(decrypted.toString()); })();

关于sodium-plus的文档可以在Github上找到。

如果您想要一个循序渐进的教程,这篇dev.to文章可以满足您的需要。

其他回答

现代浏览器现在支持加密。微妙的API,它提供本地加密和解密功能(异步!)使用这些方法之一:AES-CBC, AES-CTR, AES-GCM,或RSA-OAEP。

https://www.w3.org/TR/WebCryptoAPI/#dfn-Crypto

CryptoJS怎么样?

这是一个可靠的加密库,有很多功能。它实现哈希器,HMAC, PBKDF2和密码。在这种情况下,你需要的是密码。在项目主页上查看快速启动quide。

你可以用AES做一些类似的事情:

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>

<script>
    var encryptedAES = CryptoJS.AES.encrypt("Message", "My Secret Passphrase");
    var decryptedBytes = CryptoJS.AES.decrypt(encryptedAES, "My Secret Passphrase");
    var plaintext = decryptedBytes.toString(CryptoJS.enc.Utf8);
</script>

至于安全性,在我写这篇文章的时候,AES算法被认为是不可破解的

编辑:

似乎在线URL下降&你可以使用下载的文件从下面给定的链接加密&把各自的文件放在应用程序的根文件夹中。

https://code.google.com/archive/p/crypto-js/downloads

或使用其他CDN,如https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/aes-min.js

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase"); //U2FsdGVkX18ZUVvShFSES21qHsQEqZXMxQ9zgHy+bu0= var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase"); //4d657373616765 document.getElementById("demo1").innerHTML = encrypted; document.getElementById("demo2").innerHTML = decrypted; document.getElementById("demo3").innerHTML = decrypted.toString(CryptoJS.enc.Utf8); Full working sample actually is: <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js" integrity="sha256-/H4YS+7aYb9kJ5OKhFYPUjSJdrtV6AeyJOtTkw6X72o=" crossorigin="anonymous"></script> <br><br> <label>encrypted</label> <div id="demo1"></div> <br> <label>decrypted</label> <div id="demo2"></div> <br> <label>Actual Message</label> <div id="demo3"></div>

地下室。精细AES-GCM,独立,已测试:

async function aesGcmEncrypt(plaintext, password)

async function aesGcmDecrypt(ciphertext, password) 

https://gist.github.com/chrisveness/43bcda93af9f646d083fad678071b90a

不再支持CryptoJS。如果你想继续使用它,你可以切换到这个url:

<script src=“https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js”></script>