首页 > 解决方案 > 在 HTML5 SPA 中进行有效负载签名的有效方法

问题描述

我正在寻求实现一些有效(即具有良好性能)的逻辑,在我们的 Web 应用程序中进行有效负载签名。目标是让 HTML5 客户端保证接收到的有效负载的内容确实是我们后端生成的内容。

我们不想使用共享 salt 生成有效负载哈希,因为用户可以轻松打开 HTML5 源并找到 salt 短语。

我们现在已经实现了 RSA 签名,我们的后端使用其私钥添加有效负载签名,而我们的 HTML5 客户端使用其烘焙的公钥对其进行验证。然而,签名生成过程需要 250 毫秒(对于相对较小的有效负载),并且由于签名请求的性质,这个时间量是不可接受的。

唯一的另一个想法是在每次客户端初始化其与后端的会话时在运行时生成一个共享密钥。然而,这个秘密不能以明文形式发送,所以看起来我们将不得不实现一个 Diffie-Hellman 交换机制,如果可能的话,我们希望避免这种情况,或者使用现有的库实现自动化。

请记住,由于我们销售产品的性质,保密和加密需要在应用层完成。我们不希望加密我们的流量,这是我们的客户可能会或可能不会实施的东西(因为它是一个 Intranet 应用程序)。但是,我们必须避免将与我们的许可检查机制等相关的内容暴露给他们。后端不是基于云的,也不由我们控制,而是安装在客户的机器上,在本地。

前端是 Javascript,后端是 Java。

标签: javascriptjavasingle-page-applicationdiffie-hellmanshared-secret

解决方案


请注意,Diffie-Hellman 交换机制不受MITM 攻击的保护,因此不加密流量意味着您需要对来自服务器的 DH 数据进行身份验证。这就是为什么使用基于 DH 的密码套件的 Web 服务器使用其服务器证书的私钥对通过网络发送的 DH 元素进行签名,以便客户端检查这些元素是否真的来自他想要连接的服务器。这些元素是公开的,但需要签名。

您所说的“使用共享盐生成有效负载哈希”是一个密钥哈希消息身份验证代码,因此它基于共享秘密,正如您所注意到的,并且由于您不想使用此机制,这意味着您不信任客户。因此,您必须使用非对称加密来签署您的有效负载。

使用非对称算法对服务器有效负载进行签名意味着您首先需要让服务器与客户端共享一个公钥。由于您不对客户端和服务器之间的数据进行加密,因此您需要在客户端源代码中部署服务器公钥。

您谈论签名生成过程,但是客户端的签名检查过程在您的情况下也非常重要,因为用户等待结果的总时间是签名时间和检查时间的加法签名(此外,如果要签名的数据不是动态生成的,则通常可以在服务器上预期签名,但永远无法预期验证)。因此,您需要一种在客户端检查签名的快速方法。首先,签署一个哈希,而不是整个有效载荷。然后在客户端选择您的开发环境中可用的最快的非对称签名算法。请注意,对于对应于相同安全级别的相应密钥长度,检查 RSA 签名比检查 DSA 或 ECDSA 签名更快。所以你应该继续使用 RSA。

直到这条线的所有这些可能对您没有太大帮助!现在有一种方法可以提高性能,使用 RSA 进行签名和验证签名,这种方法与 SSL/TLS 在从同一服务器下载多个页面或其他对象时提高浏览器性能的方法相同:使用会话缓存. 您与一个特定用户共享特定会话的公共机密。永远不要将这个公共秘密用于其他会话。当用户第一次连接时,只使用一次 RSA,交换一个临时的共享密钥或交换 DH 材料来创建这个共享密钥。然后,每次服务器需要对一个对象进行签名时,它都会使用这个特定的秘密创建一个带有密钥的散列消息身份验证代码。因此,如果用户发现秘密,例如使用他的浏览器的调试模式,这不是问题:这个秘密只是在这里帮助他知道来自服务器的东西没有被改变。所以用户不能使用这个秘密来改变服务器和其他用户之间的数据交换。


推荐阅读