Поиск ключа для стрима

This commit is contained in:
serega6531
2020-04-23 23:53:44 +03:00
parent 0e460011c2
commit 200dde7940
4 changed files with 87 additions and 41 deletions

View File

@@ -20,16 +20,17 @@ import ru.serega6531.packmate.service.optimization.tls.numbers.ContentType;
import ru.serega6531.packmate.service.optimization.tls.numbers.HandshakeType; import ru.serega6531.packmate.service.optimization.tls.numbers.HandshakeType;
import ru.serega6531.packmate.service.optimization.tls.records.ApplicationDataRecord; import ru.serega6531.packmate.service.optimization.tls.records.ApplicationDataRecord;
import ru.serega6531.packmate.service.optimization.tls.records.HandshakeRecord; import ru.serega6531.packmate.service.optimization.tls.records.HandshakeRecord;
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.BasicRecordContent; import ru.serega6531.packmate.service.optimization.tls.records.handshakes.*;
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ClientHelloHandshakeRecordContent;
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.HandshakeRecordContent;
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ServerHelloHandshakeRecordContent;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -50,9 +51,9 @@ public class TlsDecryptor {
packets.forEach(p -> tlsPackets.putAll(p, createTlsHeaders(p))); packets.forEach(p -> tlsPackets.putAll(p, createTlsHeaders(p)));
ClientHelloHandshakeRecordContent clientHello = (ClientHelloHandshakeRecordContent) var clientHello = (ClientHelloHandshakeRecordContent)
getHandshake(tlsPackets.values(), HandshakeType.CLIENT_HELLO).orElseThrow(); getHandshake(tlsPackets.values(), HandshakeType.CLIENT_HELLO).orElseThrow();
ServerHelloHandshakeRecordContent serverHello = (ServerHelloHandshakeRecordContent) var serverHello = (ServerHelloHandshakeRecordContent)
getHandshake(tlsPackets.values(), HandshakeType.SERVER_HELLO).orElseThrow(); getHandshake(tlsPackets.values(), HandshakeType.SERVER_HELLO).orElseThrow();
byte[] clientRandom = clientHello.getRandom(); byte[] clientRandom = clientHello.getRandom();
@@ -64,17 +65,24 @@ public class TlsDecryptor {
Matcher matcher = cipherSuitePattern.matcher(cipherSuite.name()); Matcher matcher = cipherSuitePattern.matcher(cipherSuite.name());
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
matcher.find(); matcher.find();
String blockCipher = matcher.group(1); String blockCipher = matcher.group(1); //TODO использовать не только AES256
String hashAlgo = matcher.group(2); String hashAlgo = matcher.group(2);
//TODO var certificateHandshake = ((CertificateHandshakeRecordContent)
RSAPrivateKey privateKey = keysHolder.getKey(null); getHandshake(tlsPackets.values(), HandshakeType.CERTIFICATE).orElseThrow());
List<byte[]> chain = certificateHandshake.getRawCertificates();
byte[] rawCertificate = chain.get(0);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate certificate = cf.generateCertificate(new ByteArrayInputStream(rawCertificate));
RSAPublicKey publicKey = (RSAPublicKey) certificate.getPublicKey();
RSAPrivateKey privateKey = keysHolder.getKey(publicKey.getModulus());
if(privateKey == null) { if(privateKey == null) {
log.warn("Key for modulus not found: {}", "TODO"); log.warn("Key for modulus not found: {}", publicKey.getModulus());
return; return;
} }
BasicRecordContent clientKeyExchange = (BasicRecordContent) var clientKeyExchange = (BasicHandshakeRecordContent)
getHandshake(tlsPackets.values(), HandshakeType.CLIENT_KEY_EXCHANGE).orElseThrow(); getHandshake(tlsPackets.values(), HandshakeType.CLIENT_KEY_EXCHANGE).orElseThrow();
byte[] encryptedPreMaster = TlsKeyUtils.getClientRsaPreMaster(clientKeyExchange.getContent(), 0); byte[] encryptedPreMaster = TlsKeyUtils.getClientRsaPreMaster(clientKeyExchange.getContent(), 0);
@@ -110,17 +118,15 @@ public class TlsDecryptor {
byte[] serverFinishedEncrypted = getFinishedData(tlsPackets, false); byte[] serverFinishedEncrypted = getFinishedData(tlsPackets, false);
Cipher clientCipher = createCipher(clientEncryptionKey, clientIV, clientFinishedEncrypted); Cipher clientCipher = createCipher(clientEncryptionKey, clientIV, clientFinishedEncrypted);
// byte[] clientFinishedData = clientCipher.update(clientFinishedEncrypted);
// HandshakeRecord clientFinished = HandshakeRecord.newInstance(clientFinishedData, 16, clientFinishedData.length - 16);
Cipher serverCipher = createCipher(serverEncryptionKey, serverIV, serverFinishedEncrypted); Cipher serverCipher = createCipher(serverEncryptionKey, serverIV, serverFinishedEncrypted);
// byte[] serverFinishedData = serverCipher.update(serverFinishedEncrypted);
// HandshakeRecord serverFinished = HandshakeRecord.newInstance(serverFinishedData, 16, serverFinishedData.length - 16);
for (Map.Entry<Packet, TlsPacket.TlsHeader> entry : tlsPackets.entries()) { for (Packet packet : packets) {
if (entry.getValue().getContentType() == ContentType.APPLICATION_DATA) { List<TlsPacket.TlsHeader> tlsData = (List<TlsPacket.TlsHeader>) tlsPackets.get(packet);
byte[] data = ((ApplicationDataRecord) entry.getValue().getRecord()).getData();
boolean client = entry.getKey().isIncoming(); for (TlsPacket.TlsHeader tlsPacket : tlsData) {
if (tlsPacket.getContentType() == ContentType.APPLICATION_DATA) {
byte[] data = ((ApplicationDataRecord) tlsPacket.getRecord()).getData();
boolean client = packet.isIncoming();
byte[] decoded; byte[] decoded;
@@ -132,7 +138,8 @@ public class TlsDecryptor {
decoded = clearDecodedData(decoded); decoded = clearDecodedData(decoded);
String string = new String(decoded); String string = new String(decoded);
System.out.println(string); log.info(string);
}
} }
} }
} }
@@ -158,7 +165,7 @@ public class TlsDecryptor {
} }
private byte[] getFinishedData(ListMultimap<Packet, TlsPacket.TlsHeader> tlsPackets, boolean incoming) { private byte[] getFinishedData(ListMultimap<Packet, TlsPacket.TlsHeader> tlsPackets, boolean incoming) {
return ((BasicRecordContent) getHandshake(tlsPackets.asMap().entrySet().stream() return ((BasicHandshakeRecordContent) getHandshake(tlsPackets.asMap().entrySet().stream()
.filter(ent -> ent.getKey().isIncoming() == incoming) .filter(ent -> ent.getKey().isIncoming() == incoming)
.map(Map.Entry::getValue) .map(Map.Entry::getValue)
.flatMap(Collection::stream), HandshakeType.ENCRYPTED_HANDSHAKE_MESSAGE)) .flatMap(Collection::stream), HandshakeType.ENCRYPTED_HANDSHAKE_MESSAGE))
@@ -169,7 +176,7 @@ public class TlsDecryptor {
return stream.filter(p -> p.getContentType() == ContentType.HANDSHAKE) return stream.filter(p -> p.getContentType() == ContentType.HANDSHAKE)
.map(p -> ((HandshakeRecord) p.getRecord())) .map(p -> ((HandshakeRecord) p.getRecord()))
.filter(r -> r.getHandshakeType() == handshakeType) .filter(r -> r.getHandshakeType() == handshakeType)
.map(r -> ((BasicRecordContent) r.getContent())) .map(r -> ((BasicHandshakeRecordContent) r.getContent()))
.findFirst() .findFirst()
.orElseThrow(); .orElseThrow();
} }

View File

@@ -2,10 +2,7 @@ package ru.serega6531.packmate.service.optimization.tls.records;
import org.pcap4j.util.ByteArrays; import org.pcap4j.util.ByteArrays;
import ru.serega6531.packmate.service.optimization.tls.numbers.HandshakeType; import ru.serega6531.packmate.service.optimization.tls.numbers.HandshakeType;
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.BasicRecordContent; import ru.serega6531.packmate.service.optimization.tls.records.handshakes.*;
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ClientHelloHandshakeRecordContent;
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.HandshakeRecordContent;
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ServerHelloHandshakeRecordContent;
import ru.serega6531.packmate.utils.BytesUtils; import ru.serega6531.packmate.utils.BytesUtils;
import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES;
@@ -37,7 +34,7 @@ public class HandshakeRecord implements TlsRecord {
if (handshakeType == HandshakeType.ENCRYPTED_HANDSHAKE_MESSAGE) { if (handshakeType == HandshakeType.ENCRYPTED_HANDSHAKE_MESSAGE) {
this.handshakeLength = length; this.handshakeLength = length;
this.content = BasicRecordContent.newInstance( this.content = BasicHandshakeRecordContent.newInstance(
rawData, offset, handshakeLength); rawData, offset, handshakeLength);
return; return;
} }
@@ -50,8 +47,11 @@ public class HandshakeRecord implements TlsRecord {
} else if (handshakeType == HandshakeType.SERVER_HELLO) { } else if (handshakeType == HandshakeType.SERVER_HELLO) {
this.content = ServerHelloHandshakeRecordContent.newInstance( this.content = ServerHelloHandshakeRecordContent.newInstance(
rawData, offset + CONTENT_OFFSET, handshakeLength); rawData, offset + CONTENT_OFFSET, handshakeLength);
} else if (handshakeType == HandshakeType.CERTIFICATE) {
this.content = CertificateHandshakeRecordContent.newInstance(
rawData, offset + CONTENT_OFFSET, handshakeLength);
} else { } else {
this.content = BasicRecordContent.newInstance( this.content = BasicHandshakeRecordContent.newInstance(
rawData, offset + CONTENT_OFFSET, handshakeLength); rawData, offset + CONTENT_OFFSET, handshakeLength);
} }
} }

View File

@@ -2,7 +2,7 @@ package ru.serega6531.packmate.service.optimization.tls.records.handshakes;
import org.pcap4j.util.ByteArrays; import org.pcap4j.util.ByteArrays;
public class BasicRecordContent implements HandshakeRecordContent { public class BasicHandshakeRecordContent implements HandshakeRecordContent {
/** /**
* 0x0 - Content * 0x0 - Content
@@ -11,14 +11,14 @@ public class BasicRecordContent implements HandshakeRecordContent {
private byte[] content; private byte[] content;
public static BasicRecordContent newInstance(byte[] rawData, int offset, int length) { public static BasicHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) {
if(length > 0) { if(length > 0) {
ByteArrays.validateBounds(rawData, offset, length); ByteArrays.validateBounds(rawData, offset, length);
} }
return new BasicRecordContent(rawData, offset, length); return new BasicHandshakeRecordContent(rawData, offset, length);
} }
public BasicRecordContent(byte[] rawData, int offset, int length) { public BasicHandshakeRecordContent(byte[] rawData, int offset, int length) {
content = new byte[length]; content = new byte[length];
if (length > 0) { if (length > 0) {
System.arraycopy(rawData, offset, content, 0, length); System.arraycopy(rawData, offset, content, 0, length);

View File

@@ -0,0 +1,39 @@
package ru.serega6531.packmate.service.optimization.tls.records.handshakes;
import org.pcap4j.util.ByteArrays;
import ru.serega6531.packmate.utils.BytesUtils;
import java.util.ArrayList;
import java.util.List;
public class CertificateHandshakeRecordContent implements HandshakeRecordContent {
private static final int CERTIFICATES_LENGTH_OFFSET = 0;
private static final int CERTIFICATES_OFFSET = 3;
private int certificatesLength;
private List<byte[]> rawCertificates = new ArrayList<>();
public static CertificateHandshakeRecordContent newInstance(byte[] rawData, int offset, int length) {
return new CertificateHandshakeRecordContent(rawData, offset, length);
}
public CertificateHandshakeRecordContent(byte[] rawData, int offset, int length) {
this.certificatesLength = BytesUtils.getThreeBytesInt(rawData, CERTIFICATES_LENGTH_OFFSET + offset);
int cursor = CERTIFICATES_OFFSET + offset;
while (cursor < offset + length) {
int certificateLength = BytesUtils.getThreeBytesInt(rawData, cursor);
cursor += 3;
ByteArrays.validateBounds(rawData, cursor, certificateLength);
byte[] certData = ByteArrays.getSubArray(rawData, cursor, certificateLength);
rawCertificates.add(certData);
cursor += certificateLength;
}
}
public List<byte[]> getRawCertificates() {
return rawCertificates;
}
}