我在理解TLS / SSL如何处理电子邮件方面遇到了一些问题。
我有一些问题。
我得到的错误消息是:“握手时远程主机关闭连接”。
当我将相同的代码部署到我们的登台环境并发送电子邮件时,代码首次正常运行。 开发和登台服务器都在同一个网络中,并且都没有运行的反病毒程序。
我唯一可以想到的是,为什么它在开发环境中第一次没有工作,因为我正在使用调试器逐步调试代码,因为这样做速度较慢。
您是否知道我收到此错误的原因?
2a)或者我还需要以某种方式指定证书吗?
2b)或者此代码是从服务器获取证书并使用证书加密数据并将加密数据来回发送到电子邮件服务器?
我知道它应该像这里描述的那样工作: RFC 3207定义了SMTP连接如何使用加密。建立连接后,客户端发出STARTTLS命令。如果服务器接受此,则客户端和服务器协商加密机制。如果协商成功,则随后在它们之间传递的数据将被加密。
2c)下面的代码是这样做的吗?
5.4
答案 0 :(得分:0)
- 在我的开发机器中,如果我调试下面的代码失败,第一次在“sslSocket.startHandshake()”行上的arround,但如果我马上再试一次,它工作正常。
醇>
我得到的错误消息是:“握手期间远程主机关闭连接”。 []
我唯一可以想到的是,为什么它在开发环境中第一次没有工作是因为我正在使用调试器逐步执行代码,因为这样做速度较慢。
如果您只是在底层套接字关闭后再次执行startHandshake()
,它就永远不会有效。如果你回去做TCP连接(例如new Socket(host,port)
)和初始的SMTP交换和STARTTLS,那么我希望它可以避免影响以前连接的任何问题。
是的,服务器因为调试时的延迟而超时很可能,但确定你需要检查服务器上的日志。
- 下面的代码是创建一个SSL套接字。我很想知道这段代码是否足以使与邮件服务器的连接安全。这些SSLSocketFactory类是否自己处理证书?
醇>
间接地,是的。 SSLSocketFactory
创建一个SSLSocket
链接到SSLContext
,其中包含TrustManager
,该SSLContext
通常从信任库文件加载。您的代码默认为默认TrustManager
,其默认信任库中加载了jssecacerts
,如果存在,则为文件cacerts
,lib/security
中为jssecacerts
您正在运行的JRE中的目录。如果您的JRE未被修改(由您或您系统上授权的任何其他人),根据您的变体或Java包装,已安装的JRE通常没有cacerts
并且包含或链接到setEnabledProtocols()
(最初)包含大约一百个“知名”或已建立的证书颁发机构(如Symantec,GoDaddy,Comodo等)的根证书的文件。
2a)或者我还需要以某种方式指定证书吗?
因为握手完成后它很成功,显然不是。
2b)或者此代码是从服务器获取证书并使用证书加密数据并将加密数据来回发送到电子邮件服务器?
有点/有点/不完全。在此处不适用的一些例外情况下,在SSL / TLS握手中,服务器始终提供自己的证书,通常是中间或“链”证书,将其证书链接到受信任的根证书(例如上述Symantec等)。服务器证书始终用于验证服务器,有时单独但通常与其他机制(特别是Diffie-Hellman短暂DHE或其椭圆曲线变量ECDHE)结合用于建立一组几个对称密钥值,然后用于在两个方向上加密和验证数据。有关更完整的解释,请参阅security.SX中的规范问题和(多部分!)答案。https://security.stackexchange.com/questions/20803/how-does-ssl-work/
2c)下面的代码是这样做的吗?
它正在现有套接字上启动SSLv3或TLSv1客户端会话。我不确定你在这里有什么问题。
你可能最好不要遗漏.getSupportedProtocols
。 Sun / Oracle Java版本8是现在唯一支持的版本,默认情况下支持TLS 1.0,1.1和1.2。 1.1,尤其是1.2绝对优于1.0,并且绝对应该提供,以便如果服务器支持它们,它们就会被使用。 (Sun / Oracle 7更有问题;它实现 1.1和1.2,但默认情况下启用它们是客户端。在那里我会看{{1}}和如果支持1.1和1.2但未启用,我会添加启用它们。但如果可能的话,我只会升级到8.其他版本的Java,尤其是IBM,在加密细节方面存在显着差异。)
除非绝对必要,否则不应提供SSLv3 ;它现在被POODLE严重破坏了(在security.SX上搜索了几十个关于POODLE的Q)。我会尝试没有它,只有当服务器坚持要暂时重新启用它时,尽可能使用TLS 1.0到1.2,并同时敦促服务器升级,以便我可以再次删除它。