Java JSSE TLS-此连接在两个方向上都安全加密了吗?
在Java中使用JSSE和TLS。我已经在服务器和客户端之间创建了一个安全套接字。在最终使套接字安全连接之后,我仍然有一个关于现有代码安全性的基本问题。我遵循了一个教程中的说明,有时候JavaDoc中的文档非常精确,但有点模糊,除非你说的是斯瓦赫利方言的行话 我在C++中已经有相当一段时间的网络编程了。向Java的转换很容易。然而,最近我发现让交通更安全是明智的。这就是说: 我想用web浏览器创建安全套接字的方法创建一个安全套接字,这样双向的流量都会被加密。客户端可以看到从服务器发送的个人帐户信息(如果被截获,则非常糟糕),客户端可以安全地将其用户名和密码发送到服务器(如果被截获,则非常糟糕) 我知道所有关于公钥密码术的工作原理,但是单是公钥密码术就有一个副作用。将公钥发送到客户端,客户端使用公钥进行加密,并将数据发送到只有服务器才能解密的服务器。现在据我所知,服务器使用私钥加密发送到客户端的消息,需要添加另一层安全性,以防止任何拥有公钥的人能够解密它Java JSSE TLS-此连接在两个方向上都安全加密了吗?,java,network-programming,ssl,jsse,Java,Network Programming,Ssl,Jsse,在Java中使用JSSE和TLS。我已经在服务器和客户端之间创建了一个安全套接字。在最终使套接字安全连接之后,我仍然有一个关于现有代码安全性的基本问题。我遵循了一个教程中的说明,有时候JavaDoc中的文档非常精确,但有点模糊,除非你说的是斯瓦赫利方言的行话 我在C++中已经有相当一段时间的网络编程了。向Java的转换很容易。然而,最近我发现让交通更安全是明智的。这就是说: 我想用web浏览器创建安全套接字的方法创建一个安全套接字,这样双向的流量都会被加密。客户端可以看到从服务器发送的个人帐户信
KeyStore keyStore;
TrustManagerFactory tmf;
KeyManagerFactory kmf;
SSLContext sslContext;
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextInt();
keyStore = KeyStore.getInstance("JKS");
keyStore.load(this.getClass().getClassLoader().getResourceAsStream("server.public"),"public".toCharArray());
tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keyStore);
kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, "public".toCharArray());
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), secureRandom);
SSLSocketFactory sslsocketfactory = sslContext.getSocketFactory();
SSLSocket sslsocket = (SSLSocket)sslsocketfactory.createSocket("localhost", 9999);
服务器类:
String passphrase = "secret"
KeyStore keyStore;
TrustManagerFactory tmf;
KeyManagerFactory kmf;
SSLContext sslContext;
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextInt();
keyStore = KeyStore.getInstance("JKS");
keyStore.load(this.getClass().getClassLoader().getResourceAsStream("server.private"),passphrase.toCharArray());
tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keyStore);
kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, passphrase.toCharArray());
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), secureRandom);
SSLServerSocketFactory sslserversocketfactory = sslContext.getServerSocketFactory();
SSLServerSocket sslserversocket =
(SSLServerSocket)sslserversocketfactory.createServerSocket(9999);
/*********问题*********/
一切正常!我将套接字连接到BufferedReader和BufferedWriter,并在accept()之后开始漂亮地来回交谈;从客户端断开连接并启动客户端和服务器发送/接收循环
现在我知道客户端到服务器的通信是安全的。只有服务器密钥可以解密来自客户端的通信。但是服务器到客户端的通信呢?客户端的密钥可以解密来自服务器的消息,但是在公钥加密101中,您了解到客户端现在应该向se发送公钥服务器。在这段代码中,这是在幕后发生的吗?SSLContext解决了这个问题吗?或者现在我有了从客户端到服务器的加密连接,我现在是否也需要为客户端生成私钥/公钥对
请告诉我上述代码中发送和接收的通信量是否在两个方向上都是安全的。您确实了解PKI的工作原理,但缺少SSL实现的两个关键部分。首先,大多数PKI算法允许以两种方式对通信量进行加密。您可以使用公钥发送加密消息,并且只能使用谁有私钥的人可以读取它,这称为加密。你也可以使用私钥加密消息,任何拥有公钥的人都可以解密它,这称为数字签名 另一个缺失部分是SSL不使用PKI在客户端和服务器之间发送网络流量。它使用对称加密算法。但是对称加密的密钥(称为会话密钥)建立了使用PKI和证书的相当复杂的挑战响应协议,在这个阶段服务器向客户端证明它不是中间人,如果有更强的认证,客户端可以向服务器证明它是证书,并且建立对称的会话密钥。他们来了 对称密钥用于使用诸如RC5或AES之类的算法对流量进行加密。SSL/TLS中的证书(及其私钥)仅用于对SSL/TLS中的各方进行身份验证(通常,只有服务器使用证书) 实际加密是使用在握手过程中协商的共享/对称密钥完成的,这些密钥来自使用身份验证密钥交换形式交换的预主密钥(请参阅) 这种经过身份验证的密钥交换的方式取决于密码套件,但最终结果是相同的:双方之间共享一个预主密钥,保证只有客户端和服务器知道该密钥的证书是私钥 在预主密钥交换之后,计算主密钥本身,从中导出一对密钥(如中所述):一个用于客户端写入(和服务器读取),另一个用于服务器写入(和客户端读取)。(还生成MAC密钥,以保证连接完整性。) 原则上,并非所有密码套件都提供加密和经过身份验证的密钥交换(请参阅),但所有在JSSE中默认使用SunJSSE提供程序启用的密码套件都提供加密和经过身份验证的密钥交换(请参阅SunJSSE提供程序文档中的内容)。简而言之,不要在密码套件的名称中使用
anon
或NULL
关于您的代码:
- 有多个修复密钥/TrustManagerFactory算法的代码示例,如(“SunX509”)。这通常是硬编码Java 1.4默认值的代码。自Java 5以来,默认TMF算法是
(请参阅)。解决此问题的最佳方法是使用PKIX
(与KMF相同),这也将允许您的代码在不支持TrustManagerFactory.getDefaultAlgorithm()
(例如IBM)的其他JRE上运行SunX509
- 由于您没有使用客户端证书身份验证,因此在客户端使用
是没有意义的。您可以使用一个可能根本没有私钥的密钥库来初始化它,这使得它毫无意义。您还可以使用KeyManagerFactory
sslContext.init(null,tmf.getTrustManagers(),null)