Last active
April 30, 2024 12:11
-
-
Save benmmurphy/11349193 to your computer and use it in GitHub Desktop.
SSLKEYLOGFILE for java
This file contains hidden or 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
import java.io.IOException; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.nio.ByteBuffer; | |
import java.nio.channels.FileChannel; | |
import java.nio.file.FileSystems; | |
import java.nio.file.StandardOpenOption; | |
import java.security.InvalidAlgorithmParameterException; | |
import java.security.Provider; | |
import java.security.SecureRandom; | |
import java.security.Security; | |
import java.security.spec.AlgorithmParameterSpec; | |
import java.util.Map; | |
import javax.crypto.KeyGeneratorSpi; | |
import javax.crypto.SecretKey; | |
import javax.net.ssl.SSLSocket; | |
import javax.net.ssl.SSLSocketFactory; | |
import sun.security.internal.spec.TlsMasterSecretParameterSpec; | |
import com.sun.crypto.provider.TlsMasterSecretGenerator; | |
public class TLSLoggingProvider extends Provider{ | |
private static FileChannel logFile; | |
public TLSLoggingProvider() { | |
super("TLSLoggingProvider", 0.1, ""); | |
put("KeyGenerator.SunTlsMasterSecret", | |
MasterSecretGenerator.class.getName()); | |
put("Alg.Alias.KeyGenerator.SunTls12MasterSecret", | |
"SunTlsMasterSecret"); | |
} | |
private static Object getStaticField(Class c, String name) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { | |
Field f = c.getDeclaredField(name); | |
f.setAccessible(true); | |
return f.get(null); | |
} | |
public static void install() throws IOException { | |
String file = System.getenv("SSLKEYLOGFILE"); | |
if (file != null) { | |
logFile = FileChannel.open(FileSystems.getDefault().getPath(file), StandardOpenOption.APPEND, StandardOpenOption.CREATE); | |
TLSLoggingProvider provider = new TLSLoggingProvider(); | |
try { | |
Security.insertProviderAt(provider, 1); | |
Map verified = (Map)getStaticField(Class.forName("javax.crypto.JceSecurity"), "verificationResults"); | |
verified.put(provider, Boolean.TRUE); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
} | |
public static void main(String[] args) throws Exception { | |
install(); | |
SSLSocket socket = (SSLSocket)SSLSocketFactory.getDefault().createSocket("62.252.169.167", 443); | |
socket.startHandshake(); | |
socket.getOutputStream().write("GET / HTTP/1.1\r\nHost:google.com\r\n\r\n".getBytes("UTF-8")); | |
socket.getOutputStream().flush(); | |
socket.getInputStream().read(); | |
} | |
public static class MasterSecretGenerator extends KeyGeneratorSpi { | |
private KeyGeneratorSpi delegate; | |
private TlsMasterSecretParameterSpec spec; | |
public MasterSecretGenerator() { | |
this.delegate = new TlsMasterSecretGenerator(); | |
} | |
private Object invoke(Object o, String method) { | |
try { | |
Method m = o.getClass().getDeclaredMethod(method); | |
m.setAccessible(true); | |
return m.invoke(o); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private Object invoke(Object o, String method, Class[] types, Object... args) { | |
try { | |
Method m = o.getClass().getDeclaredMethod(method, types); | |
m.setAccessible(true); | |
return m.invoke(o, args); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); | |
public static String bytesToHex(byte[] bytes) { | |
char[] hexChars = new char[bytes.length * 2]; | |
for ( int j = 0; j < bytes.length; j++ ) { | |
int v = bytes[j] & 0xFF; | |
hexChars[j * 2] = hexArray[v >>> 4]; | |
hexChars[j * 2 + 1] = hexArray[v & 0x0F]; | |
} | |
return new String(hexChars); | |
} | |
@Override | |
protected SecretKey engineGenerateKey() { | |
SecretKey secret = (SecretKey)invoke(delegate, "engineGenerateKey"); | |
String entry = "CLIENT_RANDOM " + bytesToHex(spec.getClientRandom()) + " " + bytesToHex(secret.getEncoded()) + "\n"; | |
try { | |
logFile.write(ByteBuffer.wrap(entry.getBytes("ASCII"))); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
return secret; | |
} | |
@Override | |
protected void engineInit(SecureRandom arg0) { | |
invoke(delegate, "engineInit", new Class[]{SecureRandom.class}, arg0); | |
} | |
@Override | |
protected void engineInit(AlgorithmParameterSpec arg0, SecureRandom arg1) | |
throws InvalidAlgorithmParameterException { | |
this.spec = (TlsMasterSecretParameterSpec)arg0; | |
invoke(delegate, "engineInit", new Class[]{AlgorithmParameterSpec.class, SecureRandom.class}, spec, arg1); | |
} | |
@Override | |
protected void engineInit(int arg0, SecureRandom arg1) { | |
invoke(delegate, "engineInit", new Class[]{int.class, SecureRandom.class}, arg0, arg1); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment