抛出NoSuchAlgorithException的Java SSL代码 [英] Java SSL code throwing NoSuchAlgorithException

查看:496
本文介绍了抛出NoSuchAlgorithException的Java SSL代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个我想要添加SSL的项目,所以我创建了一个简单的客户端/服务器测试实现,看看它是否有效,我得到一个NoSuchAlgorithmException。以下是我的服务器代码抛出异常:

I'm working on a project that I want to add SSL to, so I created a simple client/server test implementation to see if it worked and I get a NoSuchAlgorithmException. The following is my server code which is throwing the exception:

import java.io.*;
import java.net.*;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.*;

public class SslServer
{
    private static final int PORT = 5555;

    public static void main(String[] args)
    {
        SecureRandom sr = new SecureRandom();
        sr.nextInt();

        try {
            //client.public is the keystore file that holds the client's public key (created with keytool)
            KeyStore clientKeyStore = KeyStore.getInstance("JKS");
            clientKeyStore.load(new FileInputStream("client.public"), "clientpublicpw".toCharArray());

            //server.private is the key pair for the server (created with keytool)
            KeyStore serverKeyStore = KeyStore.getInstance("JKS");
            clientKeyStore.load(new FileInputStream("server.private"), "serverprivatepw".toCharArray());

            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(clientKeyStore);

            //This next line is where the exception occurs
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("TLS");
            kmf.init(serverKeyStore, "serverprivatepw".toCharArray());

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), sr);

            SSLServerSocketFactory sf = sslContext.getServerSocketFactory();
            SSLServerSocket ss = (SSLServerSocket)sf.createServerSocket(SslServer.PORT);
            ss.setNeedClientAuth(true);

            BufferedReader in = new BufferedReader(new InputStreamReader(ss.accept().getInputStream()));

            String line = null;
            while((line = in.readLine()) != null)
            {
                System.out.println(line);
            }
            in.close();
            ss.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }

}

堆栈跟踪我得到的是:

java.security.NoSuchAlgorithmException: TLS KeyManagerFactory not available
    at sun.security.jca.GetInstance.getInstance(Unknown Source)
    at javax.net.ssl.KeyManagerFactory.getInstance(Unknown Source)
    at SslServer.main(SslServer.java:32)

我尝试用SSL替换TLS,但我仍然遇到了同样的异常。那对我来说没有意义。如何不支持TLS和SSL?这是我第一次尝试实现SSL,并且很难通过代码示例找到有关此问题的良好资源。任何人都可以告诉我为什么我得到这个例外或指出我的代码有问题吗?

I tried replacing "TLS" with "SSL" and I still got the same exception. That Didn't make sense to me. How can TLS and SSL not be supported? This is my first time trying to implement SSL and it seems difficult to find good resources about this with code examples that are well explained. Can anyone tell me why I am getting this exception or point out something wrong with my code?

推荐答案

有很多问题:


  • 它被称为 TLS (传输层安全性),而不是 TSL (对于 SSLContext )。

  • 我建议使用默认值: TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())(Oracle JRE上的默认值为 PKIX

  • 编辑:)默认 KeyManagerFactory SunX509 (此处不存在 TLS )。再次,使用 getDefaultAlgorithm()

  • 您应该关闭 FileInputStream 一次你已经阅读过了。

  • 目前尚不清楚为什么你在同一个地方同时拥有一个客户端和一个服务器密钥库。这些应该是两个程序:一个用于客户端和服务器( setNeedClientAuth(true)仅在服务器端有用)。如果它实际上是你的密钥库,那么将它称为客户存储之外的东西会更清楚。 (此外,由于您似乎正在学习如何使这项工作,我建议首先尝试没有客户端证书身份验证,在这种情况下,服务器将不需要信任库:使用 null 作为 SSLContext.init(...)的第二个参数,使用默认值。)

  • 不要将服务器密钥库提供给客户端。仅将其证书导出到将用作信任库的新密钥库中。每个实体(客户端和服务器)都应该将自己的私钥保密。

  • 这不是你想要的远程方的公钥(仅)您的信任存储:它将是证书。确保您不仅导入了其公钥,还输入了整个证书。

  • 为了澄清,请保留适当的文件扩展名:使用 .jks 为您的 JKS 密钥库,这将在以后为您节省麻烦。

  • 您可以使用 SSLContext.init(...)中的 SecureRandom 为null :这将使用根据安全提供商的默认值。

  • It's called TLS (Transport Layer Security), not TSL (for the SSLContext).
  • I'd suggest using the default here: TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) (The default will be PKIX on the Oracle JRE`)
  • () The default KeyManagerFactory is SunX509 (TLS doesn't exist here). Again, use getDefaultAlgorithm().
  • You should close your FileInputStream once you've read them.
  • It's not clear why you have both a client and a server keystore at the same place. These should be two programs: one for the client and the server (and setNeedClientAuth(true) is only useful on the server side). It would be clearer to call it something else than "client store" if it's effectively your keystore. (In addition, since you seem to be learning how to make this work, I'd suggest trying without client-certificate authentication first, in which case, the server won't need a truststore: use null as a second parameter of SSLContext.init(...) to use the default value.)
  • DO NOT give the server keystore to the client. Only export its certificate into a new keystore which you will use as a trust store. Each entity (client and server) should keep their own private keys private.
  • It's not so much the public key (only) of the remote party you want in your trust-store: it's going to be its certificate. Make sure you haven't only imported its public key, but the entire certificate.
  • For clarify, keep the appropriate extensions to your files: use .jks for your JKS keystore, this will save you headaches later.
  • You can use null for the SecureRandom in SSLContext.init(...): this will use the default value according to the security provider.

这样的事情会更好:

KeyStore trustStore = KeyStore.getInstance("JKS");
InputStream tsis = new FileInputStream("trustedcerts.jks");
trustStore.load(tsis, "clientpublicpw".toCharArray());
tsis.close();

KeyStore serverKeyStore = KeyStore.getInstance("JKS");
InputStream ksis = new FileInputStream("server.jks");
clientKeyStore.load(ksis.close(), "serverprivatepw".toCharArray());
ksis.close();

TrustManagerFactory tmf = 
    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);

KeyManagerFactory kmf = 
    KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(serverKeyStore, "serverprivatepw".toCharArray());

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

SSLServerSocketFactory sf = sslContext.getServerSocketFactory();
SSLServerSocket ss = (SSLServerSocket)sf.createServerSocket(SslServer.PORT);
ss.setNeedClientAuth(true);

这篇关于抛出NoSuchAlgorithException的Java SSL代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆