13

我想在 Java 服务器应用程序中打开一个安全的侦听套接字。我知道推荐的方法就是这样做:

SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = ssf.createServerSocket(443);

但这需要在启动 java 时将服务器的证书传递给 JVM。因为这会使部署中的某些事情对我来说更加复杂,所以我更愿意在运行时加载证书。

所以我有一个密钥文件和一个密码,我想要一个服务器套接字。我如何到达那里?好吧,我阅读了文档,我能找到的唯一方法是:

// these are my parameters for SSL encryption
char[] keyPassword =  "P@ssw0rd!".toCharArray();
FileInputStream keyFile = new FileInputStream("ssl.key"); 

// init keystore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyFile, keyPassword);
// init KeyManagerFactory
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyPassword);
// init KeyManager
KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
// init the SSL context
SSLContext sslContext = SSLContext.getDefault();
sslContext.init(keyManagers, null, new SecureRandom());
// get the socket factory
SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory();

// and finally, get the socket
ServerSocket serverSocket = socketFactory.createServerSocket(443);

这甚至没有任何错误处理。真的有那么复杂吗?没有更简单的方法吗?

4

3 回答 3

8

但这需要在启动 java 时将服务器的证书传递给 JVM。

不,它没有。只需在创建之前设置这些系统属性SSLServerSocket:

javax.net.ssl.keyStore ssl.key
javax.net.ssl.keyStorePassword P@ssw0rd!

您可以使用System.setProperties() 在命令行上执行此操作。

于 2012-09-11T23:31:57.047 回答
2

如果你看一下代码,你就会明白为什么它一定很复杂。此代码将 SSL 协议的实现从以下方面解耦:

  • 您的密钥材料的来源 ( KeyStore)
  • 证书算法选择和密钥管理 ( KeyManager)
  • 对等信任规则的管理 ( TrustManager) - 此处未使用
  • 安全随机算法 ( SecureRandom)
  • NIO 或套接字实现 ( SSLServerSocketFactory) - 可SSLEngine用于 NIO

考虑一下如果您尝试实现相同的目标,您自己的实现会是什么样子!

于 2012-09-11T14:15:14.377 回答
1

用这个。

public class KeyMaster
{
     public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
    catch(Exception e)
    {
        Assistance.log("Err: getSSLSocketFactory(), ");
    }

    return null;
}

public static SSLServerSocketFactory getSSLServerSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getServerSocketFactory();
    }
    catch(Exception e)
    {
        Assistance.log("Err: getSSLSocketFactory(), ");
    }

    return null;
}

public static SSLServerSocket getSSLServerSocket(SSLServerSocketFactory socketFactory, int port)
{
    try
    {
        return (SSLServerSocket) socketFactory.createServerSocket(port);
    }
    catch(Exception e)
    {Assistance.log("Err: getSSLSocket(), ");}

    return null;
}

public static KeyStore getFromPath(String path, String algorithm, String filePassword)//PKSC12
{
    try
    {
        File f = new File(path);

        if(!f.exists())
            throw new RuntimeException("Err: File not found.");

        FileInputStream keyFile = new FileInputStream(f);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(keyFile, filePassword.toCharArray());
        keyFile.close();

        return keystore;
    }
    catch(Exception e)
    {
        Assistance.log("Err: getFromPath(), " + e.toString());
    }

    return null;
}

主要是。

 KeyStore key = KeyMaster.getFromPath(".\\cssl.pfx", "PKCS12", "123");
        SSLServerSocketFactory fac = KeyMaster.getSSLServerSocketFactory(key, "TLS");
        listener = KeyMaster.getSSLServerSocket(fac, 49015);
于 2018-06-17T14:20:34.650 回答