是否有任何 SHA-256 javascript 实现通常被认为是值得信赖的?

我正在为一个论坛编写一个登录名,需要在发送到服务器之前在 javascript 中哈希密码客户端。我很难找出哪个 SHA-256实现我可以真正信任。我希望有一些权威的脚本,每个人都使用,但我发现负载不同的项目都有自己的实现。

我意识到使用别人的密码总是一个信仰的飞跃,除非你有资格自己检查它,而且没有“可信赖”的普遍定义,但这似乎是一个足够普遍和重要的东西,应该有一些共识什么使用。我很天真吗?

编辑,因为它在注释中经常出现: 是的,我们在服务器端再次执行更严格的散列。客户端散列不是我们保存在数据库中的最终结果。客户端哈希是因为人类客户端请求它。他们没有给出具体的原因,也许他们只是喜欢过度杀戮。

272564 次浏览

不,没有办法使用浏览器 JavaScript 来提高密码安全性。我强烈建议你阅读 这篇文章。就你而言,最大的问题是先有鸡还是先有蛋的问题:

交付 Javascript 密码学有什么“先有鸡还是先有蛋”的问题?

如果您不信任网络提供密码,或者更糟糕的是,不信任服务器不保守用户机密,那么您就不能信任它们提供安全代码。在您引入加密之前嗅探密码或阅读日记的攻击者只是在您引入加密之后劫持了加密代码。

[...]

为什么我不能使用 TLS/SSL 来传递 Javascript 加密代码?

你可以的。这比听起来要难,但是您可以使用 SSL 安全地将 Javascript 加密传输到浏览器。问题是,在用 SSL 建立了一个安全通道之后,您不再需要 Javascript 加密; 您拥有了“真正的”加密。

这就导致了这样的结果:

在 Javascript 中运行加密代码的问题在于,实际上加密所依赖的任何函数都可能被用于构建宿主页面的任何内容片段悄悄地覆盖。加密安全可以在进程的早期被撤销(通过生成伪造的随机数,或者篡改算法使用的常量和参数) ,或者在后期(通过将关键材料偷偷带回给攻击者) ,或者——-在最有可能的情况下-通过完全绕过加密。

对于任何一段 Javascript 代码来说,都没有可靠的方法来验证它的执行环境。Javascript 加密代码不能问,“我真的在处理一个随机数生成器,还是攻击者提供的一个随机数生成器的传真?”它当然不能断言“除了我,作者,赞同的方式,没有人被允许对这个加密秘密做任何事情”。这两个属性通常在其他使用加密的环境中提供,在 Javascript 中是不可能的。

基本上问题是这样的:

  • 您的客户端不信任您的服务器,因此他们希望添加额外的安全代码。
  • 该安全代码由您的服务器(它们不信任的服务器)传递。

或者,

  • 您的客户端不信任 SSL,所以他们希望您使用额外的安全代码。
  • 该安全代码通过 SSL 传递。

注: 此外,SHA-256不适合这一点,因为它是如此容易 强行无盐非迭代密码。如果您决定无论如何都要这样做,请查找 地下室脚本PBKDF2的实现。

过时: 许多现代浏览器现在对加密操作都有一流的支持。


斯坦福大学加密图书馆包含 SHA-256的实现。虽然 JS 中的加密技术并不像其他实现平台那样经过严格审查,但这个项目至少部分是由 Dan Boneh开发的,在一定程度上也是由 Dan Boneh赞助的。 Dan Boneh在加密技术领域是一个公认的、值得信赖的名字,这意味着这个项目有一些监督者,而这些监督者实际上知道他在做什么。该项目也得到了 国家科学基金会的支持。

值得一提的是..。
... 如果你在提交密码之前在客户端破解它,那么 哈希是密码和原始密码就变得无关紧要了。攻击者只需拦截散列即可模拟用户,如果该散列未经修改存储在服务器上,则为 然后服务器以纯文本形式存储 < em > true password (hash)

因此您的安全性现在是 更糟,因为您将 加上你自己的改进决定为以前的受信任方案。

Forge 的 SHA-256实现是快速和可靠的。

要在几个 SHA-256 JavaScript 实现上运行测试,请转到 http://brillout.github.io/test-javascript-hash-implementations/

我机器上的结果表明,Forge 是最快的实现,而且比公认答案中提到的 Stanford Javascript Crypto Library (sjcl)要快得多。

Forge 的大小是256 KB,但是提取 SHA-256相关代码将大小减少到4.5 KB,参见 https://github.com/brillout/forge-sha256

除了 Tyler 提到的斯坦福自由党。我发现 Jsrssign非常有用(Github repo here: https://github.com/kjur/jsrsasign)。我不知道它到底有多值得信赖,但是我已经使用过它的 API SHA256、 Base64、 RSA、 x509等,它工作得很好。事实上,它还包括斯坦福大学的自由解放运动。

如果你想做的只是 SHA256,Jsrssign可能是一个过度杀伤。但如果你在相关领域有其他需求,我觉得这是一个很好的适合。

我发现这个实现非常容易使用,而且还有一个慷慨的 BSD 风格的许可证:

https://github.com/Caligatio/jsSHA

我需要一个快速的方法来获得 SHA-256散列的十六进制字符串表示,它只需要3行:

var sha256 = new jsSHA('SHA-256', 'TEXT');
sha256.update(some_string_variable_to_hash);
var hash = sha256.getHash("HEX");

https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest上,我发现了这个使用内部 js 模块的代码片段:

async function sha256(message) {
// encode as UTF-8
const msgBuffer = new TextEncoder().encode(message);


// hash the message
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);


// convert ArrayBuffer to Array
const hashArray = Array.from(new Uint8Array(hashBuffer));


// convert bytes to hex string
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
return hashHex;
}

请注意,crypto.subtle只能在 httpslocalhost上使用-例如,对于使用 python3 -m http.server的本地开发,您需要将这一行添加到您的 /etc/hosts: 0.0.0.0 localhost

重新启动-您可以打开与工作 crypto.subtlelocalhost:8000

对于那些感兴趣的人,这是使用 sjcl创建 SHA-256散列的代码:

import sjcl from 'sjcl'


const myString = 'Hello'
const myBitArray = sjcl.hash.sha256.hash(myString)
const myHash = sjcl.codec.hex.fromBits(myBitArray)

可以使用 CryptoJS-https://www.npmjs.com/package/crypto-js

import sha256 from 'crypto-js/sha256'


const hash = sha256('Text')

Js 有一个 SHA256(https://docs.ethers.io/v5/api/utils/hashing/)

const { ethers } = require('ethers');
ethers.utils.sha256(ethers.utils.toUtf8Bytes('txt'));

Js-sha256 是一个 npm 包,您可以使用它,与流行的 cryp.sub 不同,后者只能在安全连接(localhost/https)上工作,而且无论如何都可以工作。当然,拥有一个安全的连接仍然是最好的。我当时使用的是 crypt.milty,它总是可以工作的,因为我使用 localhost 运行我的 webapp,当我在服务器上尝试它的时候,它就失败了。我必须切换到 js-sha256 npm 包作为临时解决方案,直到可以配置安全连接。