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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18338890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 11:32:34  来源:igfitidea点击:

Are there any SHA-256 javascript implementations that are generally considered trustworthy?

hashjavascriptsha256sha2

提问by jono

I am writing a login for a forum, and need to hash the password client side in javascript before sending it on to the server. I'm having trouble figuring out which SHA-256 implementation I can actually trust. I was expecting there to be some kind of authoritative script that everyone used, but I'm finding loads of different projects all with their own implementations.

我正在为论坛编写登录名,并且需要在将密码客户端发送到服务器之前在 javascript 中散列密码客户端。我无法确定我真正可以信任的 SHA-256 实现。我期待有某种每个人都使用的权威脚本,但我发现大量不同的项目都有自己的实现。

I realize using other people's crypto is always a leap of faith unless you're qualified to review it yourself, and that there is no universal definition of "trustworthy", but this seems like something common and important enough that there ought to be some kind of consensus on what to use. Am I just naive?

我意识到使用其他人的加密货币总是一种信念的飞跃,除非你有资格自己它,并且“值得信赖”没有通用的定义,但这似乎是一些普遍且重要的事情,应该有某种形式使用什么的共识。我只是天真吗?

Edit since it comes up a lot in the comments: Yes, we do a more stringent hash again on the server side. The client side hashing is not the final result that we save in the database. The client side hashing is because the human client requests it. They have not given a specific reason why, probably they just like overkill.

编辑,因为它在评论中出现了很多:是的,我们在服务器端再次进行了更严格的散列。客户端散列不是我们保存在数据库中的最终结果。客户端散列是因为人类客户端请求它。他们没有给出具体的原因,可能他们只是喜欢矫枉过正。

回答by tylerl

The Stanford JS Crypto Librarycontains an implementation of SHA-256. While crypto in JS isn't really as well-vetted an endeavor as other implementation platforms, this one is at least partially developed by, and to a certain extent sponsored by, Dan Boneh, who is a well-established and trusted name in cryptography, and means that the project has some oversight by someone who actually knows what he's doing. The project is also supported by the NSF.

斯坦福JS加密库包含SHA-256的实现。虽然 JS 中的加密并没有像其他实现平台那样经过严格,但该平台至少部分由Dan Boneh开发,并在一定程度上由Dan Boneh赞助,Dan Boneh是密码学领域知名且值得信赖的名字,并且意味着该项目受到了真正知道他在做什么的人的一些监督。该项目也得到了NSF 的支持。

It's worth pointing out, however...
... that if you hash the password client-side before submitting it, then the hash is the password, and the original password becomes irrelevant. An attacker needs only to intercept the hash in order to impersonate the user, and if that hash is stored unmodified on the server, then the server is storing the truepassword (the hash) in plain-text.

然而,值得指出的是......
如果您在提交密码之前对客户端进行散列,那么散列就是密码,原始密码变得无关紧要。攻击者只需拦截散列即可模拟用户,如果该散列未经修改地存储在服务器上,则服务器以纯文本形式存储真实密码(散列)

So your security is now worsebecause you decided add your own improvementsto what was previously a trusted scheme.

因此,您的安全性现在变得更糟,因为您决定对以前受信任的方案添加自己的改进

回答by Vitaly Zdanevich

On https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digestI found this snippet that uses internal js module:

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

async function sha256(message) {
    // encode as UTF-8
    const msgBuffer = new TextEncoder('utf-8').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 => ('00' + b.toString(16)).slice(-2)).join('');
    return hashHex;
}

Note that crypto.subtlein only available on httpsor localhost- for example for your local development with python3 -m http.serveryou need to add this line to your /etc/hosts: 0.0.0.0 localhost

请注意,crypto.subtle仅适用于httpslocalhost- 例如对于您的本地开发,python3 -m http.server您需要将此行添加到您的/etc/hosts0.0.0.0 localhost

Reboot - and you can open localhost:8000with working crypto.subtle.

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

回答by brillout

Forge's SHA-256 implementation is fast and reliable.

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

To run tests on several SHA-256 JavaScript implementations, go to http://brillout.github.io/test-javascript-hash-implementations/.

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

The results on my machine suggests forge to be the fastest implementation and also considerably faster than the Stanford Javascript Crypto Library (sjcl) mentioned in the accepted answer.

我机器上的结果表明,forge 是最快的实现,而且比接受的答案中提到的斯坦福 Javascript 加密库 (sjcl) 快得多。

Forge is 256 KB big, but extracting the SHA-256 related code reduces the size to 4.5 KB, see https://github.com/brillout/forge-sha256

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

回答by Brendan Long

No, there's no way to use browser JavaScript to improve password security. I highly recommend you read this article. In your case, the biggest problem is the chicken-egg problem:

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

What's the "chicken-egg problem" with delivering Javascript cryptography?

If you don't trust the network to deliver a password, or, worse, don't trust the server not to keep user secrets, you can't trust them to deliver security code. The same attacker who was sniffing passwords or reading diaries before you introduce crypto is simply hiHymaning crypto code after you do.

提供 Javascript 密码学的“鸡蛋问题”是什么?

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

[...]

[...]

Why can't I use TLS/SSL to deliver the Javascript crypto code?

You can. It's harder than it sounds, but you safely transmit Javascript crypto to a browser using SSL. The problem is, having established a secure channel with SSL, you no longer need Javascript cryptography; you have "real" cryptography.

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

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

Which leads to this:

这导致了这个:

The problem with running crypto code in Javascript is that practically any function that the crypto depends on could be overridden silently by any piece of content used to build the hosting page. Crypto security could be undone early in the process (by generating bogus random numbers, or by tampering with constants and parameters used by algorithms), or later (by spiriting key material back to an attacker), or --- in the most likely scenario --- by bypassing the crypto entirely.

There is no reliable way for any piece of Javascript code to verify its execution environment. Javascript crypto code can't ask, "am I really dealing with a random number generator, or with some facsimile of one provided by an attacker?" And it certainly can't assert "nobody is allowed to do anything with this crypto secret except in ways that I, the author, approve of".These are two properties that often are provided in other environments that use crypto, and they're impossible in Javascript.

在 Javascript 中运行加密代码的问题在于,实际上加密所依赖的任何功能都可能被用于构建托管页面的任何内容静默覆盖。加密安全可以在过程的早期(通过生成虚假的随机数,或通过篡改算法使用的常量和参数)或稍后(通过将密钥材料返回给攻击者)或——在最有可能的情况下被撤销--- 完全绕过加密。

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

Basically the problem is this:

基本上问题是这样的:

  • Your clients don't trust your servers, so they want to add extra security code.
  • That security code is delivered by your servers (the ones they don't trust).
  • 您的客户不信任您的服务器,因此他们想要添加额外的安全代码。
  • 该安全代码由您的服务器(他们不信任的服务器)提供。

Or alternatively,

或者,

  • Your clients don't trust SSL, so they want you use extra security code.
  • That security code is delivered via SSL.
  • 您的客户不信任 SSL,因此他们希望您使用额外的安全代码。
  • 该安全代码通过 SSL 提供。

Note: Also, SHA-256 isn't suitable for this, since it's so easy to brute force unsalted non-iterated passwords. If you decide to do this anyway, look for an implementation of bcrypt, scryptor PBKDF2.

注意:此外,SHA-256 不适合于此,因为它很容易暴力破解未加盐的非迭代密码。如果您决定这样做,请寻找bcryptscryptPBKDF2 的实现

回答by Danny Sullivan

For those interested, this is code for creating SHA-256 hash using sjcl:

对于那些感兴趣的人,这是使用以下方法创建 SHA-256 哈希的代码sjcl

import sjcl from 'sjcl'

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

回答by cobbzilla

I found this implementation very easy to use. Also has a generous BSD-style license:

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

jsSHA: https://github.com/Caligatio/jsSHA

jsSHA: https://github.com/Caligatio/jsSHA

I needed a quick way to get the hex-string representation of a SHA-256 hash. It only took 3 lines:

我需要一种快速的方法来获取 SHA-256 哈希的十六进制字符串表示。只用了 3 行:

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

回答by Faraway

Besides the Stanford lib that tylerl mentioned. I found jsrsasignvery useful (Github repo here:https://github.com/kjur/jsrsasign). I don't know how exactly trustworthy it is, but i've used its API of SHA256, Base64, RSA, x509 etc. and it works pretty well. In fact, it includes the Stanford lib as well.

除了 tylerl 提到的斯坦福库。我发现jsrsasign非常有用(这里的 Github 存储库:https: //github.com/kjur/jsrsasign)。我不知道它到底有多值得信赖,但我使用了它的 SHA256、Base64、RSA、x509 等 API,并且运行良好。事实上,它还包括斯坦福库。

If all you want to do is SHA256, jsrsasignmight be a overkill. But if you have other needs in the related area, I feel it's a good fit.

如果您只想做 SHA256,那么 jsrsasign可能有点矫枉过正。但是如果你在相关领域有其他需求,我觉得它很合适。