我正在研究需要对各种服务器发出HTTPS请求的搜寻器。因此,我希望我的搜寻器支持所有可能的协议/密码。
我目前正在使用Java 8,但愿意进行升级(不要紧)。
我按如下方式创建了SSLContext:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
我想每个支持TLSv1.3的服务器也都支持1.2。
这将向后兼容吗?即支持TLS 1.1 / 1.0和SSL?
(如今,SSL是否还在使用?)
为了保证成功进行SSL / TLS握手,我还需要做些什么?
谢谢!
答案 0 :(得分:2)
因此,我希望我的搜寻器支持所有可能的协议/密码。
我目前正在使用Java 8,但愿意进行升级(不要紧)。我想每个支持TLSv1.3的服务器也都支持1.2。
这将向后兼容吗?即支持TLS 1.1 / 1.0和SSL?
(如今,甚至还使用SSL吗?)
是的,至少在不久的将来,几乎所有支持1.3的人都将支持1.2,除了一些专门测试1.3兼容性的站点。 (我敢打赌,很多人甚至会继续支持1.1,例如PCI尽管仍然勉强允许它,但是您并不需要它;任何支持1.1的Java也支持1.2。)TLSv1.2
上下文支持较低版本(如果允许,请参见下文),默认的TLS
上下文还支持1.2和更低版本的(在j8 中)(在 j7 中的默认设置是 not >支持1.1和1.2客户端)。
没有人应该使用SSLv3 since 2016 at latest,并且自2014-12以来的j8u31已配置为禁止Java版本,尽管如果您更改配置以允许它,该代码仍然存在。请参见jdk.tls.disabledAlgorithms
中JRE/lib/security/java.security
的条目以获取j8或JAVA/conf/security/java.security
以获得j9或更高版本。请注意,只有通过在启动时更改配置或安全性属性,才能通过调用SSLSocket.setEnabledProtocols
和相关方法来反转这种“禁用”。相反,只要需要,就可以启用通过上下文选择“禁用”的协议,反之亦然。
自世纪之交以来,没有人应该使用SSLv2(2000或2001,取决于您的学究程度;在这种情况下,区别并不重要)。 Java不会(也从来没有)实现它。
此时使用TLSv1.0是有争议的。从理论上讲,它很容易受到BEAST的攻击,但是事实证明,这毕竟不是什么危险,现在,通过对应用程序数据进行1 / n拆分可以进一步缓解这种情况。由于Java默认包含它,因此我不会费心删除它,但是您可能会对在实际选择它的服务器上保持警惕。
您不能支持所有密码套件,因为Java不能全部实现。幸运的是您不需要。 Internet上没有人使用PSK(1.3中的恢复变体除外)SRP或Kerberos。 Java仅实现最后一个。 require Camellia SEED ARIA IDEA或AES-CCM可能很少或很少,Java都没有实现(至少在标准的密码提供程序中),尽管如果提供的话,您可能会遇到一些至少支持其中一些功能的东西。没有人应该支持RC4,“导出”套件,“ eNULL”和单DES。 Java版本再次禁止java.security
中的RC4,因为
2015年8月8u60,默认情况下禁用了很长一段时间的其他功能,以及“匿名”套件(又名“ aNULL”)。最后那是我要考虑改变的唯一一个。我可以想象出罕见但合理的情况,即在没有证书身份验证的情况下运行公共服务器,但在其他方面却是安全的。
但是,除了协议和密码之外,还有其他安全参数可以阻止连接。特别是,现在Java已配置为使用太短而不能保证安全的密钥或参数来拒绝握手,或者使用MD5签名的证书拒绝为此目的而中断,即使这些证书在两个端点都可接受的密码套件中使用。 disabledAlgorithms
中的这些设置与jdk.certpath.disabledAlgorithms
中的证书也是的设置类似,您可能需要放宽它们。使用弱化参数的连接可能会受到威胁,但是由于您大概没有任何敏感信息要发送到未知服务器,并且无论如何也不会信任您从它们接收到的任何信息,因此这种妥协可能不会一个问题。
接下来,可能最大的是证书验证。您将在许多站点中使用实际上无效的证书,还有很多站点无法通过标准Java信任库JRE/lib/security/cacerts
或类似Windows或Mozilla的证书进行验证。由于您可能根本不在乎是从真实服务器还是从合法服务器获取数据,因此可以使用非默认TrustManager
来忽略证书错误,该非默认{{1}}仅返回成功而无需实际验证服务器的证书链。如果在SO上搜索其他Q,您可能会发现一百个有人建议通过“只需剪切并粘贴此TrustManager来解决所有问题而无需任何思考,理解或努力”的情况下,建议在Java中“解决” TLS或https问题。在许多情况下,这是由实际上并不了解TLS的人员提出的,这些问题最初不是针对证书问题的,因此“解决方案”无济于事,只会在以下情况下使系统完全不安全:实际问题已解决。我认为您的问题是我所见过的第一个问题,该解决方案实际上是合适的。
最后,TLS中有一个名义上可选的功能,即服务器名称指示(SNI),许多服务器现在都需要这些功能,尤其是CDN,WAF,IDS / IPS和类似的东西,这些东西可以处理多个域的流量。根据用于建立连接的API和选项的不同,较早版本的Java并不总是发送SNI。但是,除非有意禁用 recent j8及更高版本,否则j8和更高版本应该这样做–并且您可能会发现需要<{3}}禁用它们的某些损坏的服务器。