Добавлен разбор TLS с AES128
This commit is contained in:
@@ -40,7 +40,9 @@ import java.security.cert.CertificateException;
|
|||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -101,6 +103,17 @@ public class TlsDecryptor {
|
|||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private void decryptTlsRsa(String blockCipher, String hashAlgo) {
|
private void decryptTlsRsa(String blockCipher, String hashAlgo) {
|
||||||
|
String[] blockCipherParts = blockCipher.split("_");
|
||||||
|
String blockCipherAlgo = blockCipherParts[0];
|
||||||
|
int blockCipherSize = Integer.parseInt(blockCipherParts[1]);
|
||||||
|
String blockCipherMode = blockCipherParts[2];
|
||||||
|
|
||||||
|
if (!blockCipherAlgo.equals("AES")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int keyLength = blockCipherSize / 8;
|
||||||
|
|
||||||
Optional<RSAPublicKey> publicKeyOpt = getRsaPublicKey();
|
Optional<RSAPublicKey> publicKeyOpt = getRsaPublicKey();
|
||||||
|
|
||||||
if (publicKeyOpt.isEmpty()) {
|
if (publicKeyOpt.isEmpty()) {
|
||||||
@@ -128,12 +141,12 @@ public class TlsDecryptor {
|
|||||||
TlsSecret masterSecret = preMaster.deriveUsingPRF(
|
TlsSecret masterSecret = preMaster.deriveUsingPRF(
|
||||||
PRFAlgorithm.tls_prf_sha256, ExporterLabel.master_secret, randomCS, 48);
|
PRFAlgorithm.tls_prf_sha256, ExporterLabel.master_secret, randomCS, 48);
|
||||||
byte[] expanded = masterSecret.deriveUsingPRF(
|
byte[] expanded = masterSecret.deriveUsingPRF(
|
||||||
PRFAlgorithm.tls_prf_sha256, ExporterLabel.key_expansion, randomSC, 136).extract(); // для sha256
|
PRFAlgorithm.tls_prf_sha256, ExporterLabel.key_expansion, randomSC, 72 + keyLength * 2).extract(); // для sha256
|
||||||
|
|
||||||
byte[] clientMacKey = new byte[20];
|
byte[] clientMacKey = new byte[20];
|
||||||
byte[] serverMacKey = new byte[20];
|
byte[] serverMacKey = new byte[20];
|
||||||
byte[] clientEncryptionKey = new byte[32];
|
byte[] clientEncryptionKey = new byte[keyLength];
|
||||||
byte[] serverEncryptionKey = new byte[32];
|
byte[] serverEncryptionKey = new byte[keyLength];
|
||||||
byte[] clientIV = new byte[16];
|
byte[] clientIV = new byte[16];
|
||||||
byte[] serverIV = new byte[16];
|
byte[] serverIV = new byte[16];
|
||||||
|
|
||||||
@@ -145,8 +158,8 @@ public class TlsDecryptor {
|
|||||||
bb.get(clientIV);
|
bb.get(clientIV);
|
||||||
bb.get(serverIV);
|
bb.get(serverIV);
|
||||||
|
|
||||||
Optional<Cipher> clientCipherOpt = createCipher(clientEncryptionKey, clientIV);
|
Optional<Cipher> clientCipherOpt = createCipher(blockCipherMode, clientEncryptionKey, clientIV);
|
||||||
Optional<Cipher> serverCipherOpt = createCipher(serverEncryptionKey, serverIV);
|
Optional<Cipher> serverCipherOpt = createCipher(blockCipherMode, serverEncryptionKey, serverIV);
|
||||||
|
|
||||||
if (clientCipherOpt.isEmpty() || serverCipherOpt.isEmpty()) {
|
if (clientCipherOpt.isEmpty() || serverCipherOpt.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@@ -232,8 +245,8 @@ public class TlsDecryptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows(value = {NoSuchAlgorithmException.class, NoSuchPaddingException.class})
|
@SneakyThrows(value = {NoSuchAlgorithmException.class, NoSuchPaddingException.class})
|
||||||
private Optional<Cipher> createCipher(byte[] key, byte[] iv) {
|
private Optional<Cipher> createCipher(String mode, byte[] key, byte[] iv) {
|
||||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // TLS_RSA_WITH_AES_256_CBC_SHA
|
Cipher cipher = Cipher.getInstance("AES/" + mode + "/PKCS5Padding");
|
||||||
SecretKeySpec serverSkeySpec = new SecretKeySpec(key, "AES");
|
SecretKeySpec serverSkeySpec = new SecretKeySpec(key, "AES");
|
||||||
IvParameterSpec serverIvParameterSpec = new IvParameterSpec(iv);
|
IvParameterSpec serverIvParameterSpec = new IvParameterSpec(iv);
|
||||||
|
|
||||||
|
|||||||
@@ -13,17 +13,15 @@ public class AlertLevel extends NamedNumber<Byte, AlertLevel> {
|
|||||||
public static final AlertLevel WARNING = new AlertLevel((byte) 1, "warning");
|
public static final AlertLevel WARNING = new AlertLevel((byte) 1, "warning");
|
||||||
public static final AlertLevel FATAL = new AlertLevel((byte) 2, "fatal");
|
public static final AlertLevel FATAL = new AlertLevel((byte) 2, "fatal");
|
||||||
|
|
||||||
|
public static final AlertLevel ENCRYPTED_ALERT = new AlertLevel((byte) 0, "encrypted alert");
|
||||||
|
|
||||||
public AlertLevel(Byte value, String name) {
|
public AlertLevel(Byte value, String name) {
|
||||||
super(value, name);
|
super(value, name);
|
||||||
registry.put(value, this);
|
registry.put(value, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AlertLevel getInstance(Byte value) {
|
public static AlertLevel getInstance(Byte value) {
|
||||||
if (registry.containsKey(value)) {
|
return registry.getOrDefault(value, ENCRYPTED_ALERT);
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unknown alert level: " + value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class AlertRecord implements TlsRecord {
|
|||||||
private static final int LEVEL_OFFSET = 0;
|
private static final int LEVEL_OFFSET = 0;
|
||||||
private static final int DESCRIPTION_OFFSET = LEVEL_OFFSET + BYTE_SIZE_IN_BYTES;
|
private static final int DESCRIPTION_OFFSET = LEVEL_OFFSET + BYTE_SIZE_IN_BYTES;
|
||||||
|
|
||||||
|
private int length;
|
||||||
private AlertLevel level;
|
private AlertLevel level;
|
||||||
private AlertDescription description;
|
private AlertDescription description;
|
||||||
|
|
||||||
@@ -20,12 +21,20 @@ public class AlertRecord implements TlsRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AlertRecord(byte[] rawData, int offset, int length) {
|
public AlertRecord(byte[] rawData, int offset, int length) {
|
||||||
|
this.length = length;
|
||||||
this.level = AlertLevel.getInstance(ByteArrays.getByte(rawData, LEVEL_OFFSET + offset));
|
this.level = AlertLevel.getInstance(ByteArrays.getByte(rawData, LEVEL_OFFSET + offset));
|
||||||
this.description = AlertDescription.getInstance(ByteArrays.getByte(rawData, DESCRIPTION_OFFSET + offset));
|
|
||||||
|
if (level != AlertLevel.ENCRYPTED_ALERT) {
|
||||||
|
this.description = AlertDescription.getInstance(ByteArrays.getByte(rawData, DESCRIPTION_OFFSET + offset));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return " Alert [level: " + level.name() + ", description: " + description.name() + "]";
|
if (level != AlertLevel.ENCRYPTED_ALERT) {
|
||||||
|
return " Alert [level: " + level.name() + ", description: " + description.name() + "]";
|
||||||
|
} else {
|
||||||
|
return " Encrypted Alert [" + length + " bytes]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user