Java SSL code throwing NoSuchAlgorithException

前端 未结 3 974
独厮守ぢ
独厮守ぢ 2021-02-09 10:31

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 follo

3条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-09 11:09

    There are a number of problems:

    • 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`)
    • (EDIT:) 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.

    Something like this should work better:

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

提交回复
热议问题