Java SSL sockets without authentication or stores?

2019-02-15 00:09发布

问题:

I have two java applications that need to talk to each other over an encrypted TCP socket, but they don't need to authenticate each other (one will accept() a connection from the other). Can anyone point me to a tutorial/code-snippet that will help me set these up?

I'm looking for something fairly simple and I'd like to not have to supply any keystore or truststore material.

EDIT: I should be more specific here. I meant that they don't have to authenticate each other via SSL. I have some non-trivial authentication that I have to do at the application level, so I can't use any sort of SSL-based authentication scheme.

Also, some of the links in the answers posted so far (as of noon 3/10/2010) require keystore files. Is there a simple way I can programmatically generate the keys I need?

回答1:

To reiterate Chris Jester-Young's advice - if you don't have authentication, then you might be communicating securely, but you have no idea who you're communicating securely with. You could simply be communicating very securely with the bad guy himself (who is relaying everything you're saying onto the person you hoped you were talking directly to).

However, there is a quite lightweight authentication scheme that might suit your purposes, called TOFU (Trust On First Use). This is where you use SSL and generate self-signed certificates for each side - however you do not skip certificate validation. Instead, on the first connection with a given peer you accept any certificate and store it locally; on subsequent connections with that peer, you only accept that saved certificate. This is similar to the way that ssh works by default for host authentication, and provides authentication of the "the guy I'm talking to now is the same guy I was talking to yesterday" variety.



回答2:

You can use the anonymous Diffie-Hellman ciphersuites if you insist on ignoring Chris Jester-Young's sage advice. Those ciphersuites are not enabled by default, you have to explicitly enable them, for example by using the SSLSocket.setEnabledCipherSuites() method.



回答3:

If you absolutely do not want to use SSL with certificates, you can roll your own, though it won't be as secure obviously. I'm just improvising here, mixing a little asymmetric crypto with port-knocking.

First, create a random RSA key pair in the client, in-memory, no need to store it anywhere. Client then connects to server using a plain Socket, and upon connection, sends the server the public key (encode as you wish, so that you can read it easily on the server). Server then generates a random 128-bit key, starts ANOTHER ServerSocket in a random port, and encrypts the 128-bit key and the new server port number, using the client's public key, and sends the data back to the client. Server must wait for a short period of time to receive a connection from the same client on the new port.

Client closes connection, deciphers data, and opens a new Socket to the server on the specified port. Then both client and server must wrap the socket's InputStream and OutputStream on a CipherInputStream and CipherOutputStream using AES/CBC/PKCS5Padding (or RC4 if you prefer) with the specified 128-bit key. Voilá, you have a secure connection between client and server, without any authentication.

If you want to handle authentication you can do so over the secure connection, or on the first connection the server can have RSA key pair as well, they exchange keys and the server can send a challenge to the client (the server sends the challenge to the client using the client's public key and the client responds to the challenge using the server's public key). But that's unnecessarily complicated and I think you'd be better off using standard SSL with keystores anyway... perhaps you can get create an in-memory KeyStore on the client and send it to the server as explained above using the first connection (encrypt the keystore with the server's public key) and then you can set up the second connection to use SSL with that keystore which is temporary and will be discarded when the client disconnects.