Memra

SSLSocket clients and HTTPS

◈ 5 cards

A factory instead of a constructor, an SSLSocket that IS a Socket so every stream idiom transfers, the lazy handshake, how to read a cipher suite name, and why https:// needs no new client API.

The factory replaces the constructor

javax.net.ssl.SSLSocket has only protected constructors, so you never write new SSLSocket(...). You ask an abstract factory instead:

SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
Socket socket = factory.createSocket("books.example.com", 443);

getDefault() hands back the JVM's configured implementation. createSocket is overloaded five ways, and the first four line up one-for-one with the Socket constructors you already know: host as a String or an InetAddress, optionally pinned to a local interface and local port. The fifth is the odd one — it takes an existing Socket already connected to a proxy and tunnels through it to the real destination, with a boolean autoClose deciding whether closing the outer socket closes the underlying one.

It is a Socket, so everything transfers

The returned object really is an SSLSocket, and SSLSocket extends java.net.Socket. That single fact is the whole lesson. getInputStream(), getOutputStream(), setSoTimeout, close(), try-with-resources — every idiom from Module 6 works unchanged, and so does every wrapper you would normally stack on top: BufferedReader, OutputStreamWriter with an explicit charset, DataInputStream. Encryption and decryption happen underneath the stream, invisibly. You are not learning a new I/O model; you are learning a new way to obtain the same one.

The handshake is lazy

Creating the socket connects the TCP layer, but the cryptographic handshake is deferred until it is actually needed — normally the first read or write. That is usually what you want, but it moves the interesting failures. A bad certificate, a name mismatch, or no cipher suite in common surfaces as an SSLException (a subclass of IOException) from your first read(), not from createSocket.

Call startHandshake() to force it to happen now. Do that when you want to inspect the peer before sending anything — for example to log which suite was negotiated, or to check the certificate subject yourself. getSession() then returns the SSLSession, which carries getCipherSuite(), getPeerCertificates() and the session identifier.

Sessions are also why a page load with seven resources is not seven handshakes. JSSE reuses an established session's keys across sockets to the same host and port within a short window, so only the first connection pays the full cost. You do nothing to enable this. setEnableSessionCreation(false) opts out when you would rather renegotiate every time.

Reading a cipher suite name

getSupportedCipherSuites() lists what the implementation can do; getEnabledCipherSuites() lists the subset it is currently willing to use; setEnabledCipherSuites(String[]) narrows that list, throwing IllegalArgumentException on any name the implementation does not know.

A suite name is four fields joined by underscores: protocol, key-exchange algorithm, bulk cipher, and message-digest. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 reads as: TLS, ephemeral elliptic-curve Diffie-Hellman for key agreement, RSA to authenticate that agreement, AES with a 128-bit key for the data, SHA-256 for integrity. Once you can decompose a name you can spot the dangerous ones by inspection. anon in the key-exchange field means no authentication at all. NULL in the cipher field means no encryption at all. EXPORT means a deliberately crippled key length from an era of export controls. All three are disabled by default, and all three exist as traps for someone debugging at 2 a.m.

https:// needs no new client API

Here is the payoff for everything Module 4 taught. new URL("https://books.example.com/").openStream() works. openConnection() returns an HttpsURLConnection, which extends HttpURLConnection, which extends URLConnection — so setRequestProperty, getResponseCode, getErrorStream and getContentType behave exactly as before. The protocol handler builds the SSLSocket for you. The only genuinely new methods are the ones that expose what you could not see before: getCipherSuite() and getServerCertificates().

Worked example — fetch a page over TLS and print who answered

The program is short because the security is not your code. Get the default factory, cast it, and open a socket to port 443. Call startHandshake() immediately, so a certificate problem fails here rather than three method calls later. Ask the session for the negotiated suite and the peer certificate chain, and print the subject of the first certificate — that is the identity the CA vouched for, and comparing it against the host you asked for is what step three of the last lesson's handshake actually means.

Only then send the request. Wrap getOutputStream() in an OutputStreamWriter with an explicit US-ASCII charset, write a request line, a Host header and a Connection: close header, terminate every line with \r\n, end with a blank line, and flush. Wrap getInputStream() in a BufferedReader over an InputStreamReader and read lines until null.

Delete the two startHandshake()/getSession() lines and you are left with exactly the plain-socket HTTP client from Module 6, with 443 in place of 80 and a factory in place of new. That is the measure of how little TLS asks of your code — and also the measure of how easy it is to ship without ever checking what you connected to.

SocketSSLSockethow you get onenew Socket(host, port)factory.createSocket(...)streamsgetInputStream()identicaltry-with-resourcesyesyeshandshakenonelazy, or startHandshake()peer identityunverifiedgetPeerCertificates()the type itselfjava.net.Socketa subclass of itSame streams, same close, different way to get one.
One row changes and the rest is inheritance. Because SSLSocket is a subclass of Socket, every stream idiom, timeout and try-with-resources block from Module 6 transfers untouched; the genuinely new surface is the bottom two rows, which are the ones that tell you who you are talking to.
NORMAL ~/memra/learn/comp-348/ssl-socket-clients-and-https utf-8 LF