Skip to content

Instantly share code, notes, and snippets.

@gkhays
Last active December 20, 2015 23:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gkhays/6211648 to your computer and use it in GitHub Desktop.
Save gkhays/6211648 to your computer and use it in GitHub Desktop.
This is a set of classes used to test FIPS 140-2 and SSL communications in general. The OpenSSL s_server and s_client utilities are a great resource to use as partners in the testing process.
package org.gkh.net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.logging.Logger;
import javax.net.ssl.SSLSocket;
public class ClientThread extends Thread {
private SSLSocket socket;
private InputStream in;
private OutputStream out;
private Logger logger;
public ClientThread(SSLSocket socket) throws IOException {
this.socket = socket;
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
this.logger = Logger.getLogger(ClientThread.class.getName());
}
public void run() {
try {
String line;
int available = 0;
BufferedReader cmdInput = new BufferedReader(new InputStreamReader(
System.in));
BufferedReader reader = new BufferedReader(new InputStreamReader(
this.in));
PrintWriter writer = new PrintWriter(this.out);
System.out.println("Type CTRL-Z to exit");
while ((line = cmdInput.readLine()) != null) {
logger.info("Received: " + line);
writer.println(line);
writer.flush();
if ((available = in.available()) > 0) {
logger.info("Available bytes: " + available);
System.out.println("Server: " + reader.readLine());
}
}
cmdInput.close();
this.out.close();
this.in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package org.gkh.net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.SocketException;
import java.util.logging.Logger;
import javax.net.ssl.SSLSocket;
public class ServerThread extends Thread {
private SSLSocket socket;
private InputStream in;
private OutputStream out;
private Logger logger;
private boolean isRunning;
public ServerThread(SSLSocket socket) throws IOException {
this.socket = socket;
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
this.isRunning = true;
this.logger = Logger.getLogger(ClientThread.class.getName());
logger.info("Constructing Server Thread...");
}
public void run() {
try {
while (isRunning) {
String line = null;
BufferedReader reader = new BufferedReader(
new InputStreamReader(this.in));
PrintWriter writer = new PrintWriter(this.out);
try {
line = reader.readLine();
System.out.println("Server read: " + line);
writer.println("Input received");
if (line.equals("quit")) {
isRunning = false;
}
} catch (SocketException s) {
// Connection reset
// Connection closed
// Socket write error
isRunning = false;
logger.info("The client did something we don't like: "
+ s.getMessage());
}
}
this.out.close();
this.in.close();
socket.close();
} catch (IOException e) {
logger.info("Unanticipated error, printing stack trace...");
e.printStackTrace();
}
}
}
package org.gkh.net;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class SslSocketUtils {
private SslSocketUtils() {
}
public static void enableCustomTrustManager(KeyStore jks) throws Exception
{
X509TrustManager sunX509TrustManager = null;
TrustManager[] tms = getTrustManagers(jks);
System.out.println("Found " + tms.length + " trust managers.");
for (int i = 0; i < tms.length; i++) {
if (tms[i] instanceof X509TrustManager) {
sunX509TrustManager = (X509TrustManager) tms[i];
break;
}
}
if (sunX509TrustManager == null)
throw new Exception("Missing X509 Trust Manager");
TrustManager ctm = new CustomTrustManager(sunX509TrustManager);
System.out.println("CutomTrustManager instance of TrustManager: " + (ctm instanceof TrustManager));
//TrustManager[] tms2 = new TrustManager[] { ctm };
}
public static TrustManager[] getTrustManagers()
throws KeyStoreException, NoSuchAlgorithmException
{
return getTrustManagers(null);
}
public static TrustManager[] getTrustManagers(KeyStore ks)
throws KeyStoreException, NoSuchAlgorithmException
{
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ks);
return trustManagerFactory.getTrustManagers();
}
public static void insertNssProvider(String configFile) {
Provider nss = new sun.security.pkcs11.SunPKCS11(configFile);
Security.addProvider(nss);
int sunJssePosition = -1;
int currentIndex = 0;
for (Provider provider : Security.getProviders()) {
if ("SunJSSE".equals(provider.getName())) {
sunJssePosition = currentIndex + 1;
break;
}
currentIndex++;
}
Security.removeProvider("SunJSSE");
Provider sunJsse = new com.sun.net.ssl.internal.ssl.Provider(nss);
if (sunJssePosition == -1) {
Security.addProvider(sunJsse);
} else {
Security.insertProviderAt(sunJsse, sunJssePosition);
}
System.out.println(nss.getName());
System.out.println(nss.getInfo());
}
public static void printCertificateInformation(KeyStore jks, String alias)
throws Exception {
java.security.cert.Certificate cert = jks.getCertificate(alias);
if (cert == null) {
System.out.println("Unable to retrieve certificate for " + alias
+ ".");
return;
}
String algo = cert.getPublicKey().getAlgorithm();
System.out.print("Alias '" + alias + "' public key: ");
if (algo != null)
System.out.println("Certificate public key: " + algo);
java.security.cert.Certificate[] cchain = jks
.getCertificateChain(alias);
if (cchain != null) {
List<Certificate> mylist = new ArrayList<Certificate>();
for (int i = 0; i < cchain.length; i++) {
mylist.add(cchain[i]);
}
CertificateFactory cf = CertificateFactory.getInstance("X.509");
CertPath cp = cf.generateCertPath(mylist);
System.out.println(cp);
} else
System.out.println("Certificate chain is null");
}
void printDefaultTrustManagers()
throws KeyStoreException, NoSuchAlgorithmException
{
getTrustManagers();
System.out.println("JVM Default Trust Managers:");
for (TrustManager trustManager : getTrustManagers()) {
System.out.println(trustManager);
if (trustManager instanceof X509TrustManager) {
X509TrustManager x509TrustManager = (X509TrustManager)trustManager;
System.out.println("\tAccepted issuers count : " + x509TrustManager.getAcceptedIssuers().length);
}
}
}
}
package org.gkh.net;
import javax.net.ssl.*;
class MyHandshakeListener
implements HandshakeCompletedListener
{
public void handshakeCompleted(HandshakeCompletedEvent e)
{
System.out.println("Handshake succesful!");
System.out.println("Using cipher suite: " + e.getCipherSuite());
}
}
public class TestClient
extends TestSocket
{
public TestClient(String host, int port, boolean useNss, String path,
String secret, String keypass) throws Exception {
initialize(host, port, useNss, path, secret, keypass);
}
static void usage()
{
System.out.println("TestClient <host> <port> <path> <secret> [<useNss>]");
}
public static void main(String[] args)
{
if (args.length < 4) {
usage();
return;
}
// TODO - How about an XML or JSON configuration file?
System.out.println("Starting Java test client...");
String host = args[0];
int port = Integer.parseInt(args[1]);
String path = args[2];
String secret = args[3];
boolean useNss = false;
if (args.length == 5)
useNss = Boolean.parseBoolean(args[4]);
String keypass = null;
if (args.length == 6)
keypass = args[5];
try
{
TestClient client = new TestClient(host, port, useNss, path, secret, keypass);
SSLSocket socket = client.getSocket();
System.out.println("Supported Cipher Suites: ");
for (String s : socket.getSupportedCipherSuites()) {
System.out.println(s);
}
System.out.println("Registering a handshake listener...");
socket.addHandshakeCompletedListener(new MyHandshakeListener());
System.out.println("Supported protocols:");
for (String s : socket.getEnabledProtocols())
System.out.println(s);
System.out.println("Starting handshaking...");
socket.setUseClientMode(true);
socket.startHandshake();
System.out.println("Just connected to " + socket.getRemoteSocketAddress());
String[] enabled = null;
enabled = socket.getEnabledCipherSuites();
printEnabledArray(enabled, "cipher suites");
enabled = socket.getEnabledProtocols();
printEnabledArray(enabled, "protocols");
new ClientThread(socket).start();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
package org.gkh.net;
import javax.net.*;
import javax.net.ssl.*;
public class TestServer
extends TestSocket
{
volatile int serverPort = 0;
// List of FIPS cipher suites.
// http://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html
TestServer()
{
this.isServer = true;
}
void doServerSide(int port, boolean useNss, String store, String secret,
String keypass) throws Exception {
serverPort = port;
initialize(null, port, useNss, store, secret, keypass);
ServerSocketFactory ssf = ctx.getServerSocketFactory();
SSLServerSocket sslServerSocket = (SSLServerSocket) ssf
.createServerSocket(serverPort);
sslServerSocket.setEnabledProtocols(new String[] { "TLSv1" });
String[] ciphers = sslServerSocket.getSupportedCipherSuites();
System.out.println("Supported Cipher Suites");
for (int i = 0; i < ciphers.length; i++) {
System.out.println(ciphers[i]);
}
/*
* Supported Protocols: SSLv2Hello, SSLv3, TLSv1
*/
String[] protocols = sslServerSocket.getSupportedProtocols();
System.out.println("Supported Protocols");
for (int i = 0; i < protocols.length; i++) {
System.out.println(protocols[i]);
}
String[] enabled = sslServerSocket.getEnabledCipherSuites();
System.out.println("Enabled (Server) Cipher Suites");
for (int i = 0; i < enabled.length; i++) {
System.out.println(enabled[i]);
}
sslServerSocket.setEnabledCipherSuites(ciphers);
/*
* Configured Protocol: TLSv1
* Provider:
* Info: Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)
* Name: SunJSSE
*/
System.out.println("Configured Protocol: " + ctx.getProtocol());
System.out.println("Provider: (info) " + ctx.getProvider().getInfo()
+ " (name) " + ctx.getProvider().getName());
sslServerSocket.setNeedClientAuth(true);
serverPort = sslServerSocket.getLocalPort();
System.out.println("serverPort = " + serverPort);
while (true) {
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
new ServerThread(sslSocket).start();
}
}
/**
* @param args
*/
public static void main(String[] args) throws Exception
{
int port = Integer.parseInt(args[0]);
String store = "";
String secret = "";
if (args.length >= 3) {
store = args[1];
secret = args[2];
}
boolean useNss = false;
if (args.length == 4)
useNss = Boolean.parseBoolean(args[3]);
String keypass = null;
if (args.length == 5)
keypass = args[4];
System.out.println("Starting Java test server...");
TestServer testServer = new TestServer();
testServer.doServerSide(port, useNss, store, secret, keypass);
}
}
package org.gkh.net;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
public class TestSocket
{
protected static Provider pkcs11Provider;
protected SSLContext ctx = null;
protected KeyStore jks = null;
protected TrustManagerFactory trustManagerFactory = null;
//private static String DIR = System.getProperty("DIR");
protected int port;
protected String host;
protected boolean isServer = false;
protected SSLSocket socket;
public void enablePkcsProvider(String configFile)
{
pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configFile);
Security.insertProviderAt(pkcs11Provider, 1);
new com.sun.net.ssl.internal.ssl.Provider(pkcs11Provider);
// System.out.println("FIPS Enabled");
// System.out.println(pkcs11Provider.getName());
// System.out.println(pkcs11Provider.getInfo());
}
protected void initialize(String host, int port, boolean useNss,
String path, String secret, String keypass) throws Exception {
if (Utils.isNullOrEmpty(path))
throw new Exception(
"Please specify a valid path for NSS or a Java Keystore");
this.host = host;
this.port = port;
KeyManagerFactory kmf = null;
TrustManagerFactory tmf = null;
kmf = KeyManagerFactory.getInstance("SunX509");
tmf = TrustManagerFactory.getInstance("SunX509");
char[] passphrase = secret.toCharArray();
if (true == useNss) {
// It is possible to update the provider list in java.security, but
// we have chosen to do it on-the-fly instead.
enablePkcsProvider(path);
// Server gets TrustStore from PKCS#11 token.
jks = KeyStore.getInstance("PKCS11", "SunPKCS11-NSSFIPS");
jks.load(null, passphrase);
} else {
// To just use the default Java keystore:
// ctx.init(null, null, null);
this.jks = KeyStore.getInstance("JKS");
InputStream in = new FileInputStream(path);
jks.load(in, passphrase);
}
if (Utils.isNullOrEmpty(keypass))
kmf.init(jks, passphrase);
else
kmf.init(jks, keypass.toCharArray());
tmf.init(jks);
// SSLContext Algorithms {SSL, SSLv2, SSLv3, TLS, TLSv1, TLSv1.1}
// http://download.oracle.com/javase/6/docs/technotes/guides//security/StandardNames.html#SSLContext
ctx = SSLContext.getInstance("TLSv1");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
System.out.println("Configured Protocol: " + ctx.getProtocol());
System.out.println("Provider:\n Info: " + ctx.getProvider().getInfo()
+ "\n Name: " + ctx.getProvider().getName());
// SslSocketUtils.printCertificateInformation(alias);
System.out.println("Locating socket factory for SSL...");
if (true == isServer) {
// System.out.println("Starting server socket on port " + port + "...");
// SSLServerSocketFactory serverFactory = ctx.getServerSocketFactory();
// SSLServerSocket serverSocket = (SSLServerSocket) serverFactory
// .createServerSocket(port);
// serverSocket.setEnabledProtocols(new String[] { "TLSv1" });
} else {
if (host == null) {
throw new Exception("The host must not be null");
}
SSLSocketFactory factory = ctx.getSocketFactory();
System.out
.println("Creating secure socket to " + host + ":" + port);
this.socket = (SSLSocket) factory.createSocket(host, port);
// this.socket.setEnabledProtocols(new String[] {
// "TLSv1", "SSLv3", "SSLv2Hello" });
}
}
public void setHost(String host)
{
this.host = host;
}
public void setPort(int port)
{
this.port = port;
}
public SSLSocket getSocket()
{
return this.socket;
}
public static void printEnabledArray(String[] enabled, String what)
{
System.out.println("Enabled " + what + ":");
for (String s : enabled)
{
System.out.println(" " + s);
}
}
}
@slg123
Copy link

slg123 commented Jun 17, 2014

Good stuff! I need to learn me some Java. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment