Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SSL代码抛出NoSuchAlgorithException_Java_Ssl - Fatal编程技术网

Java SSL代码抛出NoSuchAlgorithException

Java SSL代码抛出NoSuchAlgorithException,java,ssl,Java,Ssl,我正在做一个我想添加SSL的项目,所以我创建了一个简单的客户机/服务器测试实现,看看它是否有效,我得到了一个NoSuchAlgorithmException。以下是引发异常的服务器代码: import java.io.*; import java.net.*; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; imp

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

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();
        }
    }

}
我得到的stacktrace是:

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,似乎很难找到关于这方面的好资源,因为代码示例已经很好地解释过了。有人能告诉我为什么会出现这种异常,或者指出我的代码有问题吗?

有很多问题:

  • 它被称为
    TLS
    (传输层安全性),而不是
    TSL
    (用于
    SSLContext
  • 我建议在这里使用默认值:
    TrustManagerFactory tmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
    (Oracle JRE上的默认值将是
    PKIX
  • 编辑:)默认的
    KeyManagerFactory
    SunX509
    TLS
    在这里不存在)。再次使用
    getDefaultAlgorithm()
  • 阅读完
    文件输入流后,应关闭它们
  • 不清楚为什么客户机和服务器密钥库都在同一个位置。这应该是两个程序:一个用于客户端和服务器(并且
    setNeedClientAuth(true)
    仅在服务器端有用)。如果它实际上是您的密钥库,那么将其称为“客户机存储”以外的东西会更清楚。(此外,由于您似乎正在学习如何实现这一点,我建议您首先尝试不使用客户端证书身份验证,在这种情况下,服务器将不需要信任库:使用
    null
    作为
    SSLContext.init(…)
    的第二个参数以使用默认值。)
  • 不要将服务器密钥库提供给客户端。仅将其证书导出到将用作信任存储的新密钥库中。每个实体(客户端和服务器)都应该保持自己的私钥私有
  • 这与其说是您希望信任存储中的远程方的公钥(仅此),还不如说是它的证书。确保您不仅导入了它的公钥,而且还导入了整个证书
  • 为了澄清,请为文件保留适当的扩展名:使用
    .jks
    作为
    jks
    密钥库,这将为以后的工作省去麻烦
  • 您可以对
    SSLContext.init(…)
    中的
    SecureRandom
    使用
    null
    :这将根据安全提供程序使用默认值
这样的方法应该更有效:

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);

正确的SSLContext名称为“TLS”。可以找到标准算法名称的列表

请参见示例,并获取受支持算法的名称。似乎“SunX509”和“NewSunX509”是KeyManagerFactory支持的算法。协议名为TLS,而不是TSL。

k我编辑了我的帖子,添加了这一更改。即使在我使用“TLS”时,我仍然会遇到同样的异常。如果你真的担心密码,你应该直接使用
char[]
或作为密码回调,并且在实际应用程序中永远不要硬编码你的密码(请参阅)。作为旁注,等待
readLine
返回
null
并不是知道何时停止读取(从任何类型的套接字)的好方法,请参阅此处的讨论:我将代码更改为使用TrustManagerFactory.getDefaultAlgorithm()和KeyManagerFactory.getDefaultAlgorithm(),这使它正常工作。我之所以在这里同时拥有这两个密钥库,是因为服务器有:server.private和client.public,而客户端有client.private和server.public。顺便说一句,我用这个网站作为我代码的参考,不确定它有多可靠,但它是我能找到的最好的:www.ibm.com/developerworks/java/tutorials/j-jsse/index.htmlIt确实说过KMF的
SunX509
,而不是
TLS
。它还使用了相当旧的Java版本,TMF的新默认值是
PKIX
。(我仍然不相信本文中的密钥库文件命名约定。)这是一个错误类型,已修复。我仍然得到例外与“TLS”见布鲁诺的编辑,他的答案关于KeyManagerFactory,这将是你的另一个问题。再次,这是一个错误的类型,并已修复。我仍然得到例外的“TLS”你读过我的答案吗?似乎“SunX509”和“NewSunX509”是KeyManagerFactory.+1'ed支持的算法(正如我在最初的回答中键入的那样)@MattL922:
getDefaultAlgorithm()
通常是最安全的赌注。