在 Web 浏览器上下文中,有两种 SSL 连接:一种由浏览器管理,另一种由您的代码(无论是 Java、Javascript...)自行管理。
对于第一种,您大多不走运,因为浏览器不会向您提供有关服务器证书链的详细信息。浏览器告诉您“这一切都是花花公子”,但无法让您检查浏览器是否被误入歧途。
对于第二种,这意味着您的代码将打开与服务器的连接并自行运行完整的 SSL 握手。当然,此时代码将看到来自服务器的证书链,并且能够以任意方式验证它,包括“直接信任”(客户端代码已经“知道”服务器公钥)或在至少使用特定的、预期的根 CA。这种方法有几个实际问题,需要付出代价才能解决:
- 您必须嵌入完整的 SSL 实现。这不一定很大,但可能很棘手。由于您控制客户端和服务器代码,因此您可以将其缩小,因此您可以专注于您打算使用的确切协议版本和算法。
- 如果使用没有JIT 编译器的解释器,性能可能会成为问题。
- 只有当您可以确保客户端代码未被更改时,所有这些才有意义。使用 Javascript 检查有关下载 Javascript 代码本身的 SSL 连接的任何内容是没有用的:中间人可以更改 Javascript 代码以删除检查。
- 在某些网络中,从客户端代码打开到服务器的原始连接是很棘手的,尤其是在代理方面。
为了提高性能,您将需要使用Java ME。大多数 Java ME 实现都使用基本解释器,因此它不会比 Javascript 或 Flash 快,除了Java ME 标准库包括java.math.BigInteger
一个任意大整数的算术实现,它通常作为本机代码实现,因此速度非常快。对于 SSL 握手所涉及的 RSA 或 DH 计算,您将需要它。
为了确保在客户端上运行正确的代码,Java ME 可以再次进行救援,因为 Java ME 小程序可以被签名。这并不能真正解决您的问题,因为可以运行 Fiddler 的攻击者是可以在本地信任存储中插入自己的假 CA 的攻击者;同一个攻击者可以将他自己的假 CA 添加到另一个本地信任库,即用于验证 applet 签名证书的信任库。然而,这增加了一个很好的转折:如果客户端连接被拦截,事后取证检查可能会发现缓存的签名小程序,然后就会证明小程序是假的,而作为服务器维护者的你不是坏人。您无法获得这种免于身份验证的法律保护,但签名可以提供帮助。当然,这在很大程度上取决于上下文。
代理的问题很严重。很多本地网络,尤其是企业网络,不做NAT;相反,所有外部流量都必须通过一些代理。用户的 Web 浏览器知道代理在哪里,但不知道您的 Javascript 或 Java 代码。此外,代理可能需要一些身份验证,这可能与本地会话凭据相关联;再次,浏览器透明地通过,而不是您的代码。为了解决这类问题,您可能会设想通过 HTTP 请求隧道传输 SSL 流量,这些请求将移交给框架提供的 HTTP 代码。这是可能的(大约十年前我已经做到了)但并不容易。
然而,这一切都闻起来很糟糕。您所说的这种中间人攻击只有在攻击者可以穿透 X.509 信任模型时才起作用,例如,通过在客户端系统中安装他自己的恶意 CA 作为受信任的 CA。由于操作系统软件更新也使用这种信任模型,因此必须假设客户端系统在那时完全处于攻击者的控制之下,至少是潜在的。从某种意义上说,Fiddler 并不是邪恶的人使用的东西,因为 Fiddler 运作的条件也让上述邪恶的人能够实施更大更彻底的邪恶。
这可以概括为:从 Javascript 或 Java ME 客户端代码检查 SSL 连接的内容与客厅桌子上的漂亮便条一样无用,请潜在的窃贼自己打电话报警。
(不过可能在加拿大工作。)