-
-
Save djelinski/b4543a3eb7ea66306044c08b41bba00f to your computer and use it in GitHub Desktop.
An example of TLS 1.3 client and server on Java. See details in https://blog.gypsyengineer.com/en/security/an-example-of-tls-13-client-and-server-on-java.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.gypsyengineer.tlsbunny.jsse; | |
import javax.net.ssl.SSLServerSocket; | |
import javax.net.ssl.SSLServerSocketFactory; | |
import javax.net.ssl.SSLSocket; | |
import javax.net.ssl.SSLSocketFactory; | |
import java.io.*; | |
/* | |
Generate self-signed ECDSA keypair with | |
keytool -genkeypair -alias ec -keyalg EC -keysize 256 -sigalg SHA256withECDSA -validity 365 -dname "CN=localhost,OU=Unknown,O=Unknown,L=Unknown,S=Unknown,C=Unknown" -storetype JKS -keystore ectest.jks -storepass 123456 -ext KeyUsage:c=digitalSignature,keyCertSign | |
Generate self-signed ECDH keypair with | |
keytool -genkeypair -alias ec -keyalg EC -keysize 256 -sigalg SHA256withECDSA -validity 365 -dname "CN=localhost,OU=Unknown,O=Unknown,L=Unknown,S=Unknown,C=Unknown" -storetype JKS -keystore ectest.jks -storepass 123456 -ext KeyUsage:c=keyAgreement,keyCertSign | |
Adjust cipher_suites as desired or comment them out entirely | |
Run with: | |
-Djavax.net.ssl.keyStore=/path/to/ectest.jks | |
-Djavax.net.ssl.keyStorePassword=123456 | |
-Djavax.net.ssl.trustStore=/path/to/ectest.jks | |
-Djavax.net.ssl.trustStorePassword=123456 | |
*/ | |
public class ECCTest { | |
private static final int delay = 1000; // in millis | |
private static final String[] protocols = new String[] {"TLSv1.2"}; | |
public static final String[] cipher_suites = { "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" }; | |
private static final String message = | |
"Like most of life's problems, this one can be solved with bending!"; | |
public static void main(String[] args) throws Exception { | |
try (EchoServer server = EchoServer.create()) { | |
new Thread(server).start(); | |
Thread.sleep(delay); | |
try (SSLSocket socket = createSocket("localhost", server.port())) { | |
InputStream is = new BufferedInputStream(socket.getInputStream()); | |
OutputStream os = new BufferedOutputStream(socket.getOutputStream()); | |
os.write(message.getBytes()); | |
os.flush(); | |
byte[] data = new byte[2048]; | |
int len = is.read(data); | |
if (len <= 0) { | |
throw new IOException("no data received"); | |
} | |
System.out.printf("client received %d bytes: %s%n", | |
len, new String(data, 0, len)); | |
} | |
} | |
} | |
public static SSLSocket createSocket(String host, int port) throws IOException { | |
SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault() | |
.createSocket(host, port); | |
socket.setEnabledProtocols(protocols); | |
return socket; | |
} | |
public static class EchoServer implements Runnable, AutoCloseable { | |
private static final int FREE_PORT = 0; | |
private final SSLServerSocket sslServerSocket; | |
private EchoServer(SSLServerSocket sslServerSocket) { | |
this.sslServerSocket = sslServerSocket; | |
} | |
public int port() { | |
return sslServerSocket.getLocalPort(); | |
} | |
@Override | |
public void close() throws IOException { | |
if (sslServerSocket != null && !sslServerSocket.isClosed()) { | |
sslServerSocket.close(); | |
} | |
} | |
@Override | |
public void run() { | |
System.out.printf("server started on port %d%n", port()); | |
try (SSLSocket socket = (SSLSocket) sslServerSocket.accept()) { | |
System.out.println("accepted"); | |
InputStream is = new BufferedInputStream(socket.getInputStream()); | |
OutputStream os = new BufferedOutputStream(socket.getOutputStream()); | |
byte[] data = new byte[2048]; | |
int len = is.read(data); | |
if (len <= 0) { | |
throw new IOException("no data received"); | |
} | |
System.out.printf("server received %d bytes: %s%n", | |
len, new String(data, 0, len)); | |
os.write(data, 0, len); | |
os.flush(); | |
} catch (Exception e) { | |
System.out.printf("exception: %s%n", e.getMessage()); | |
} | |
System.out.println("server stopped"); | |
} | |
public static EchoServer create() throws IOException { | |
return create(FREE_PORT); | |
} | |
public static EchoServer create(int port) throws IOException { | |
SSLServerSocket socket = (SSLServerSocket) | |
SSLServerSocketFactory.getDefault().createServerSocket(port); | |
socket.setEnabledCipherSuites(cipher_suites); | |
socket.setEnabledProtocols(protocols); | |
return new EchoServer(socket); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment