Skip to content

Instantly share code, notes, and snippets.

@yuri1969
Forked from tsaarni/extract-pre-master-secret.py
Last active September 15, 2021 12:52
Show Gist options
  • Save yuri1969/071da40742a27315a3e88f61939425b9 to your computer and use it in GitHub Desktop.
Save yuri1969/071da40742a27315a3e88f61939425b9 to your computer and use it in GitHub Desktop.
Extract keys to decrypt Java TLS stream
#!/usr/bin/env python3
#
# Extract TLS pre-master secret to decrypt captured TLS stream in Wireshark
#
# Java TLS implementation can be configured to dump information on TLS stream,
# making it possible to extracting TLS key for decrypting the stream for debug
# purposes.
#
# This script is originally by Timothy Basanov
# https://timothybasanov.com/2016/05/26/java-pre-master-secret.html
#
# Run the application
# java .... -Djavax.net.debug=ssl,keygen | extract-pre-master-secret.py keys.log
# Or simply feed the log file (remove timestamp prefixes if any)
# extract-pre-master-secret.py keys.log < java-ssl.log
#
# To decode TLS stream in Wireshark
# 1. select packet with TLS layer
# 2. right-click and choose "Protocol preferences / Open Transport Layer Security Preferences"
# 3. select "keys.log" file in (Pre)-Master-Secret log filename
#
import sys
import re
def extract_data_from_line(line):
m = re.match(r'\d+:([ 0-9A-F]{51}) .*', line)
if m:
return m.group(1).replace(' ', '')
raise line
def main(args):
if len(args) != 2:
sys.exit('Usage: {} logfile.txt'.format(args[0]))
logfile = open(args[1], 'w')
parsing_mastersecret_line = 0
parsing_clientnonce_line = 0
for line in sys.stdin:
print(line, end='')
if parsing_mastersecret_line:
parsing_mastersecret_line += 1
if parsing_clientnonce_line:
parsing_clientnonce_line += 1
if line == 'Client Nonce:\n':
parsing_clientnonce_line = 1
cn = ''
if 2 <= parsing_clientnonce_line <= 3:
cn = cn + extract_data_from_line(line)
if line == 'Master Secret:\n':
parsing_mastersecret_line = 1
ms = ""
if 2 <= parsing_mastersecret_line <= 4:
ms = ms + extract_data_from_line(line)
if 5 == parsing_mastersecret_line:
print('CLIENT_RANDOM {} {}'.format(cn, ms), file=logfile)
logfile.flush()
logfile.close()
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment