当前位置: 首页 > 面试题库 >

Java中的密钥SSL套接字连接

夏涵畅
2023-03-14
问题内容

我正在加密服务器和客户端之间的TCP连接。在研究和测试过程中,我倾向于使用秘密密钥加密。我的问题是我找不到有关如何实现此功能的任何教程。我发现的教程围绕一次HTTP请求进行,我只需要一个SSL套接字。

我到目前为止编写的代码如下。我几乎可以肯定它需要扩展,我只是不知道该怎么做。任何帮助表示赞赏。

private ServerSocketFactory factory;
private SSLServerSocket serverSocket;

factory = SSLServerSocketFactory.getDefault();
serverSocket = (SSLServerSocket) factory.createServerSocket( <portNum> );

接受客户端连接的服务器代码

SSLSocket socket = (SSLSocket) serverSocket.accept();
socket.startHandshake();

我只是不知道如何实际进行握手。

参考:http
:
//docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html


问题答案:

SSL套接字连接在Java中得到很好的支持,对于您来说可能是一个不错的选择。事先要了解的一件事是,SSL同时提供加密和服务器身份验证。您不能轻易获得仅加密。作为参考,加密可以防止网络窃听,而服务器身份验证可以防止“中间人”攻击,在这种情况下,攻击者充当客户端和服务器之间的代理。

由于身份验证是SSL不可或缺的一部分,因此服务器将需要提供SSL证书,而客户端将需要能够对证书进行身份验证。服务器将需要一个“密钥库”文件来存储其证书。客户端将需要一个“信任存储”文件,在该文件中存储其信任的证书,其中之一必须是服务器的证书,或者可以从中追溯“信任链”的证书到服务器的证书。

请注意,您不必了解SSL的来龙去脉即可使用Java
SSL套接字。我确实认为通读SSL的工作方式很有意思,例如在Wikipedia上有关TLS的文章中,但是复杂的多步握手和实际连接加密的设置都由SSLServerSocket和SSLSocket类在幕后处理。

代码

以上所有内容只是背景信息,它解释了以下一些代码。该代码假定您熟悉常规的未加密套接字。在服务器上,您将需要如下代码:

/**
 * Returns an SSLServerSocket that uses the specified key store file 
 * with the specified password, and listens on the specified port.
 */
ServerSocket getSSLServerSocket(
    File keyStoreFile, 
    char[] keyStoreFilePassword,
    int port
) throws GeneralSecurityException, IOException {
    SSLContext sslContext 
        = SSLConnections.getSSLContext(keyStoreFile, keyStoreFilePassword);
    SSLServerSocketFactory sslServerSocketFactory 
        = sslContext.getServerSocketFactory();
    SSLServerSocket sslServerSocket
        = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
    return sslServerSocket;
}

然后可以像使用其他任何ServerSocket一样使用SSLServerSocket;身份验证,加密和解密将对调用代码完全透明。实际上,我自己的代码中的关联函数声明的返回类型仅为纯ServerSocket,因此调用代码不会感到困惑。

注意:如果要将JRE的默认cacerts文件用作密钥存储文件,则可以跳过创建SSLContext的行,并使用它ServerSocketFactory.getDefault()来获取ServerSocketFactory。您仍将服务器的公用/专用密钥对安装到密钥存储文件中,在本例中为cacerts文件。

在客户端上,您将需要如下代码:

SSLSocket getSSLSocket(
    File trustStoreFile,
    char[] trustStoreFilePassword,
    InetAddress serverAddress,
    port serverPort
) throws GeneralSecurityException, IOException {
    SSLContext sslContext 
        = SSLConnections.getSSLContext(trustStoreFile, trustStoreFilePassword);
    SSLSocket sslSocket 
        = (SSLSocket) sslContext.getSocketFactory().createSocket
            (serverAddress, serverPort);
    sslSocket.startHandshake();
    return sslSocket;
}

就像服务器代码中的SSLServerSocket一样,这里返回的SSLSocket就像常规的Socket一样使用;进入和退出SSLSocket的I /
O是使用未加密的数据完成的,所有加密工作都是在内部完成的。

与服务器代码一样,如果要使用默认的JRE
cacerts文件作为信任库,则可以跳过SSLContext的创建并使用SSLSocketFactory.getDefault()代替sslContext.getSocketFactory()。在这种情况下,仅当服务器的证书是自签名的或不是由主要认证机构之一签发的,才需要安装服务器的证书。另外,为确保您不信任在您信任的证书链中合法发行的证书,而是将其信任的域与尝试访问的域完全不同,则应在该行之后添加以下(未嵌套的)代码您在哪里创建SSLSocket

    sslSocket.getSSLParameters().setEndpointIdentificationAlgorithm("HTTPS");

如果您使用自己的信任库文件,但信任该文件中一个或多个证书颁发机构颁发的所有证书,或者信任该文件中不同服务器的许多证书,则这也适用。

证书,密钥库和信任库

现在,对于困难的或至少稍微困难的部分:生成和安装证书。我建议使用Java keytool(最好是1.7或更高版本)来完成这项工作。

如果要创建自签名证书,请首先使用以下命令从命令行生成服务器的密钥对:keytool -genkey -alias server -keyalg rsa -dname "cn=server, ou=unit, o=org, l=City, s=ST, c=US" -validity 365242 -keystore server_key_store_file -ext san=ip:192.168.1.129 -v。替换您自己的名称和值。特别是,此命令为IP地址为192.168.1.129的服务器创建一个密钥对,该密钥对在365242天(即1000年)内到期。如果客户端将通过域名系统查找服务器,请使用san=dns:server.example.com代替san=ip:192.168.1.129。有关keytool选项的更多信息,请使用man keytool

系统将提示您输入密钥库的密码-如果这是新的密钥库文件,则设置密钥库的密码-并设置新密钥对的密码。

现在,使用导出服务器的证书keytool -export -alias server -file server.cer -keystore server_key_store_file -rfc -v。这将创建一个server.cer包含证书以及服务器公共密钥的文件。

最后,将server.cer文件移动到客户端计算机,然后使用诸如此类将证书安装到客户端的信任存储中keytool -import -alias server -file server.cer -keystore client_trust_store_file -v。系统将提示您输入信任存储文件的密码。提示将显示“输入密钥库密码”,因为Java密钥工具可同时用于密钥库文件和信任库文件。请注意,如果您使用的是默认JRE
cacerts文件changeit,我相信初始密码是。

如果您正在使用从公认的证书颁发机构购买的证书,并且正在cacerts客户端上使用默认的JRE
文件,则只需将证书安装在服务器的密钥存储文件中;您不必弄乱客户端的文件。服务器安装说明应由证书颁发机构提供,或者您也可以再次查看man keytool说明。

关于套接字,尤其是SSL套接字,存在大量的神秘知识,但是它们实际上非常易于使用。在许多情况下,十行代码将避免需要复杂而脆弱的消息传递或消息排队基础结构。适合您考虑使用此选项。



 类似资料:
  • 这很好,但没有SSL。 我已经使用OpenSSL为服务器和客户机生成了SSL证书,结果是: 服务器的证书(PEM格式) 客户端的证书(PEM格式) 服务器的私钥(PEM格式) 客户端的私钥(PEM格式) CA文件(PEM、CER和CRT格式) null 会出什么问题?

  • 问题内容: 如何创建SSL套接字连接? 我真的需要创建密钥库吗?该密钥库应该与我所有的客户端应用程序共享吗? 我用以下代码创建了一个服务器: 我用以下代码在android上创建了一个客户端: 但是当我尝试连接时,会引发以下错误: 问题答案: 您需要一个证书来建立ssl连接,您可以在密钥库中加载证书,也可以加载证书本身。我将显示一些有关keystore选项的示例。 您的代码需要一些参数才能运行: 您

  • Hi想知道是否有办法设置套接字的超时,以及在连接握手之前重试的次数。我在非常糟糕的连接模式下测试了我的应用程序,我为我在Volley中的请求设置了重试策略为10秒,但SSL握手似乎是个问题,因为它有一个默认的超时设置为60秒,而Volley超时只被触发当套接字由于尝试次数或超时而失败时。 下面是我的方法: 我正在使用截击来提出我的请求,我实现这一点的方法是: 我还尝试设置了这样的超时:

  • 问题内容: 我正在尝试在Python中建立安全的套接字连接,而使用SSL有点麻烦。我已经找到一些有关如何与SSL建立连接的代码示例,但它们都涉及密钥文件。我尝试连接的服务器不需要接收任何密钥或证书。我的问题是,我该如何实质上包装带有SSL的python套接字连接。我知道我应该使用的密码是,协议是。这就是我一直在尝试的: 运行此代码时,没有任何错误,但响应为空。当尝试在命令行中调试此代码时,通过在终

  • 问题内容: 我正在使用的保护客户端和服务器程序之间的通信。该服务器程序还提供来自Web浏览器的HTTPS请求。 据“ 开始加密与Java ”,371页,你应该总是叫,以确保密码套件最终被谈判是为您的目的足够强。 话虽这么说,对我的方法的调用产生了大约180个选项。这些选项的范围从(我认为是相当安全的)到(不确定MD5的当前状态是否安全)到(不确定要做什么)。 限制套接字使用的密码套件的明智列表是什

  • 我试图使用PowerShell从https网站抓取html内容。 不幸的是,该站点只例外一组有限的SSL/TLS密码套件,不支持Powershell可用的套件。 如果尝试使用Invoke-WebRequest cmdlet,我会收到以下错误消息: 调用-网络请求:请求被中止:无法创建SSL/TLS安全通道。 问题: 是否有办法指定PowerShell使用的客户端SSL/TLS密码套件? 还有其他c