gpt4 book ai didi

Java JSSE TLS - 此连接是否双向安全加密?

转载 作者:搜寻专家 更新时间:2023-10-31 19:47:56 25 4
gpt4 key购买 nike

在 Java 中使用 JSSE 和 TLS。我在服务器和客户端之间创建了一个安全套接字。在最终让套接字安全连接之后,我仍然对我现有代码的安全性有一个基本问题。我按照教程中的说明进行操作,有时 JavaDoc 中的文档非常精确但有点模糊,除非你会说 Jargon 的斯瓦赫里语方言....

我使用 C++ 进行网络编程已经有一段时间了。向 Java 的过渡很容易。然而,最近我发现确保流量安全是明智的。话虽这么说:

我想以网络浏览器创建安全套接字的相同方式创建安全套接字,因此双向流量都被加密。客户端可以看到服务器发送的个人帐户信息(如果被拦截非常糟糕),客户端可以安全地将用户名和密码发送到服务器(如果被拦截也非常糟糕)。

我完全了解公钥密码术的工作原理,但单独使用公钥密码术有副作用。您将公钥发送给客户端,客户端使用公钥加密,然后将数据发送到服务器,只有服务器才能解密。现在据我了解,服务器使用私钥加密发送到客户端的消息,并且需要添加另一层安全性以防止任何拥有公钥的人能够解密它。

  1. 我有一个公钥/私钥对存储在文件 public.key 和 private.key 中(我使用 JSSE 的 keytool 实用程序制作了这些文件
  2. 我在客户端包含了public.key
  3. 我在服务器中包含了 private.key

客户端类:

    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() 之后开始漂亮地来回交谈;从客户端建立连接并启动我的客户端和服务器发送/接收循环。

现在我知道此时客户端到服务器的通信是安全的。只有服务器 key 可以解密来自客户端的流量。但是服务器到客户端的通信呢?客户端的 key 可以解密来自服务器的消息,但在 Public Key Crypto 101 中,您了解到客户端现在应该向服务器发送一个公钥。这是在这段代码的幕后发生的吗? SSLContext 是否处理了这个问题?或者现在我有一个从客户端到服务器的加密连接,我现在是否还需要为客户端生成一个私钥/公钥对?

让我知道在上面的代码中发送和接收的流量是否实际上是双向安全的。

最佳答案

SSL/TLS 中的证书(及其私钥)仅用于验证 SSL/TLS 中的各方(通常只有服务器使用证书)。

实际加密是使用在握手期间协商的共享/对称 key 完成的,从使用经过身份验证的 key 交换形式交换的预主 key 派生而来(参见 TLS Specification, Section F.1.1

这种经过身份验证的 key 交换是如何完成的取决于密码套件,但最终结果是相同的:双方共享的预主 key ,保证只有客户端和具有私钥的服务器知道其证书。

在主 key 交换之后,计算主 key 本身,从中派生出一对 key (如 Key Calculation section 中所述):一个供客户端写入(供服务器读取) ) 和一个供服务器写入(并供客户端读取)。 (同时生成 MAC secret ,以保证连接的完整性。)

原则上,并非所有密码套件都提供加密和经过身份验证的 key 交换(请参阅 Cipher Suite Definitions section ),但在 SunJSSE 提供程序中默认启用的所有密码套件都提供(请参阅 SunJSSE 提供程序文档中的 Cipher Suite tables)。简而言之,不要使用 anon 启用密码套件或 NULL在他们的名字里。

关于您的代码:

  • 有多个代码示例可以解决像这样的 Key/TrustManagerFactory 算法(“SunX509”)。这通常是硬编码 Java 1.4 默认值的代码。从 Java 5 开始,默认的 TMF 算法是 PKIX (参见 Customization section of the JSSE Reference Guide)。解决这个问题的最好方法是使用 TrustManagerFactory.getDefaultAlgorithm() (与 KMF 相同),这也将允许您的代码在不支持 SunX509 的其他 JRE 上运行(例如 IBM 的)。

  • 由于您没有使用客户端证书身份验证,因此没有必要 KeyManagerFactory在客户端。您使用可能没有私钥的 keystore 对其进行初始化,这使其毫无意义。您不妨使用 sslContext.init(null, tmf.getTrustManagers(), null) . (在这两种情况下,安全随机数都是一样的,让 JSSE 使用它的默认值。)

关于Java JSSE TLS - 此连接是否双向安全加密?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12888552/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com