【问题标题】:Are there any asymmetric encryption options for JavaScript?JavaScript 是否有任何非对称加密选项?
【发布时间】:2011-09-01 07:01:51
【问题描述】:

我必须通过 JavaScript AJAX 调用,通过未加密的通道(HTTP,而不是 HTTPS)传输一些敏感信息。

我想加密数据,但在 JavaScript 端加密意味着我公开了密钥,这使得对称加密只是一种隐蔽的安全练习。

JavaScript 有非对称加密吗?这样,我可以将服务器解密密钥保密。 (我不担心Server > JavaScript 消息的安全,只关心某个JavaScript > Server 消息的安全)

【问题讨论】:

    标签: javascript security encryption encryption-asymmetric public-key-encryption


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      服务器 > JavaScript 消息是否通过 HTTPS 发送?

      如果没有,没有什么能阻止中间人更改脚本。如果有权访问未加密数据的代码被泄露,任何加密都将毫无用处。

      【讨论】:

      • 我的问题是它是 HTTP,而不是 HTTPS。这就是我研究非对称加密的原因,这样我就可以将解密密钥保存在服务器端。这正是非对称加密所帮助解决的问题:中间人可以获得加密的消息,用于加密它的密钥,但没有解密它的密钥就不好了。
      • 中间人攻击也可以更改公钥。您还需要某种形式的身份验证,从在浏览器窗口中运行的脚本的角度来看,这有点难以做到。
      • @Erik:当然是非对称公钥。你是对的,如果攻击者可以更改公钥,他/她也可以更改页面上的代码。所以这个方案只能防止窃听。只要迈克尔知道这个方案不能防止 MITM。
      • @owl 仔细看;你说的是公钥。
      • @owl 我完全理解公钥/私钥密码学。 :) 请点击此链接阅读pubic的定义。
      【解决方案3】:

      您根本需要加密的原因可能是为了防止中间人。在某些情况下,攻击者能够嗅探流量而无法对其进行更改。该解决方案可以抵御这种威胁,但它根本无法抵御能够修改流量的中间人。

      如果攻击者可以更改流量,那么他也可以更改执行加密的脚本。最简单的攻击是从脚本中完全删除加密。如果您没有 https,并且中间人是可能的(几乎在每种情况下都是这种情况),那么您根本无法控制最后呈现的 html 或 javascript用户。攻击者可能会完全重写您的 html 代码和 javascript、禁用加密、在您的表单中创建新的表单字段等。Https 是网络通道中安全通信的先决条件。

      【讨论】:

      • 同意,JavaScript 中的加密是个坏主意。此外,目前浏览器中的 JavaScript 实现没有任何安全的随机数生成。这意味着无论其他威胁如何,在 JavaScript 中实现的任何加密都将被破解
      • 谢谢。这是有道理的——我主要考虑的是嗅探,而不是操纵。我会再考虑一下,看看 HTTPS 是否是一种选择。
      • 实际上,除非真的仔细实施,否则仅执行普通的非对称加密也不能防止窃听。通常,您使用 RSA 密钥加密对称密钥,然后使用对称会话密钥执行加密。该加密必然会使用带有某种填充的 CBC。由于处理帖子的服务是在线的,因此您现在创建了一个容易受到填充预言机攻击的方案(密码学不是很有趣吗?)。
      • @sstendal :如果连接是 https 怎么办。那么我可以在javascript中使用加密吗?我需要做公钥加密。用户的表单字段由他在客户端的私钥签名(客户端必须提供包含私钥的密钥库的位置)。并被发送到服务器。那里的服务器通过使用相应的公钥验证签名来验证正确的用户是否已签名。但我想这是不可能的。因为 javascript 是沙盒的。我猜你不能访问本地主机文件。如果我穿着,请纠正我。有什么办法可以解决吗?
      • 我们现在拥有子资源完整性developer.mozilla.org/en-US/docs/Web/Security/…。这将保护提供给浏览器的 javascript。
      【解决方案4】:

      我已经做到了。我使用这种 JavaScript 客户端非对称 RSA 加密来防止登录凭据通过 HTTP 以纯文本形式发送。

      目标是防止基于网络嗅探的登录请求重放攻击。当然,这不如 HTTPS 安全,因为它无法抵抗中间人攻击,但对于本地网络来说已经足够了。

      客户端加密使用基于JSBNTravis Tridwell's excellent work。 Travis 的网页还可以生成 RSA 私钥和公钥(如果你懒得使用openssl)。密钥以 PKCS#1 PEM 格式生成。我加密了username+password+timeInMs+timezone,这样每次登录时加密的内容都会改变。

      在服务器端,我的 Java 代码读取使用 Apache JMeter's org.apache.jmeter.protocol.oauth.sampler.PrivateKeyReader 读取 PKCS#1 PEM 文件:

      PrivateKey pk = (new PrivateKeyReader("myPrivateKeyFile.pem")).getPrivateKey();
      

      然后我使用

      解密加密的内容
      byte[] enc = DatatypeConverter.parseBase64Binary(clientData);
      Cipher rsa = Cipher.getInstance("RSA");
      rsa.init(Cipher.DECRYPT_MODE, pk);
      byte[] dec = rsa.doFinal(enc);
      String out = new String(dec, "UTF8");
      

      然后我检查客户端时间戳/时区是否与服务器端时间戳/时区匹配。如果延迟少于几秒,登录过程将继续。否则该请求被视为重放攻击,登录失败。

      【讨论】:

        【解决方案5】:

        非对称公钥/私钥是做到这一点的唯一方法。为了防止 MIM 攻击,服务器可以使用用户密码对公钥进行散列,然后用户(在浏览器中)重新计算散列 - 如果它们匹配,那么用户可以确信从服务器发送的公钥没有被篡改 - 这取决于只有服务器和用户知道用户密码的事实。

        PS 我想把这个写成评论,因为这比答案更合适,但我没有足够的积分:)

        例子见:openpgp.js

        【讨论】:

        • 你有任何关于如何使用公钥/私钥的来源吗?
        猜你喜欢
        • 2011-01-01
        • 2011-04-05
        • 2019-07-29
        • 1970-01-01
        • 2011-11-17
        • 1970-01-01
        • 2010-10-30
        • 2017-02-22
        • 2011-03-01
        相关资源
        最近更新 更多