Расшифровка TLS
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
package ru.serega6531.packmate.service.optimization;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.serega6531.packmate.utils.TlsUtils;
|
||||||
|
|
||||||
|
import javax.net.ssl.X509KeyManager;
|
||||||
|
import java.io.File;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class RsaKeysHolder {
|
||||||
|
|
||||||
|
// Key: N from RSA public key
|
||||||
|
private final Map<BigInteger, RSAPrivateKey> keys = new HashMap<>();
|
||||||
|
|
||||||
|
public void addKey(File pemFile, File keyFile) {
|
||||||
|
if(!pemFile.exists() || !keyFile.exists()) {
|
||||||
|
throw new IllegalArgumentException("One of files does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
X509KeyManager keyManager = TlsUtils.createKeyManager(pemFile, keyFile);
|
||||||
|
|
||||||
|
// X509Certificate[] certificateChain = keyManager.getCertificateChain("1");
|
||||||
|
RSAPrivateKey privateKey = ((RSAPrivateKey) keyManager.getPrivateKey("1"));
|
||||||
|
keys.put(privateKey.getModulus(), privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RSAPrivateKey getKey(BigInteger modulus) {
|
||||||
|
return keys.get(modulus);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,57 +1,54 @@
|
|||||||
package ru.serega6531.packmate.service.optimization;
|
package ru.serega6531.packmate.service.optimization;
|
||||||
|
|
||||||
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
|
import com.google.common.collect.ListMultimap;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.bouncycastle.tls.ExporterLabel;
|
import org.bouncycastle.tls.ExporterLabel;
|
||||||
import org.bouncycastle.tls.PRFAlgorithm;
|
import org.bouncycastle.tls.PRFAlgorithm;
|
||||||
import org.bouncycastle.tls.crypto.TlsSecret;
|
import org.bouncycastle.tls.crypto.TlsSecret;
|
||||||
import org.bouncycastle.tls.crypto.impl.bc.BcTlsCrypto;
|
import org.bouncycastle.tls.crypto.impl.bc.BcTlsCrypto;
|
||||||
import org.bouncycastle.tls.crypto.impl.bc.BcTlsSecret;
|
import org.bouncycastle.tls.crypto.impl.bc.BcTlsSecret;
|
||||||
|
import org.pcap4j.util.ByteArrays;
|
||||||
import ru.serega6531.packmate.model.Packet;
|
import ru.serega6531.packmate.model.Packet;
|
||||||
import ru.serega6531.packmate.service.optimization.tls.TlsPacket;
|
import ru.serega6531.packmate.service.optimization.tls.TlsPacket;
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.TlsKeyUtils;
|
import ru.serega6531.packmate.service.optimization.tls.keys.TlsKeyUtils;
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.CipherSuite;
|
import ru.serega6531.packmate.service.optimization.tls.numbers.CipherSuite;
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.ContentType;
|
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.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.BasicRecordContent;
|
||||||
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ClientHelloHandshakeRecordContent;
|
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.HandshakeRecordContent;
|
||||||
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ServerHelloHandshakeRecordContent;
|
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.ServerHelloHandshakeRecordContent;
|
||||||
import ru.serega6531.packmate.utils.TlsUtils;
|
|
||||||
|
|
||||||
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 javax.net.ssl.X509KeyManager;
|
|
||||||
import java.io.File;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
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;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TlsDecryptor {
|
public class TlsDecryptor {
|
||||||
|
|
||||||
private static final Pattern cipherSuitePattern = Pattern.compile("TLS_RSA_WITH_([A-Z0-9_]+)_([A-Z0-9]+)");
|
private static final Pattern cipherSuitePattern = Pattern.compile("TLS_RSA_WITH_([A-Z0-9_]+)_([A-Z0-9]+)");
|
||||||
|
|
||||||
private final List<Packet> packets;
|
private final List<Packet> packets;
|
||||||
|
private final RsaKeysHolder keysHolder;
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void decryptTls() {
|
public void decryptTls() {
|
||||||
File pemFile = new File(getClass().getClassLoader().getResource("tls.pem").getFile());
|
ListMultimap<Packet, TlsPacket.TlsHeader> tlsPackets = ArrayListMultimap.create(packets.size(), 1);
|
||||||
File keyFile = new File(getClass().getClassLoader().getResource("tls.key").getFile());
|
|
||||||
X509KeyManager keyManager = TlsUtils.createKeyManager(pemFile, keyFile);
|
|
||||||
|
|
||||||
X509Certificate[] certificateChain = keyManager.getCertificateChain("1");
|
packets.forEach(p -> tlsPackets.putAll(p, createTlsHeaders(p)));
|
||||||
RSAPrivateKey privateKey = ((RSAPrivateKey) keyManager.getPrivateKey("1"));
|
|
||||||
|
|
||||||
Map<Packet, List<TlsPacket.TlsHeader>> tlsPackets = packets.stream()
|
|
||||||
.collect(Collectors.toMap(p -> p, this::createTlsHeaders));
|
|
||||||
|
|
||||||
ClientHelloHandshakeRecordContent clientHello = (ClientHelloHandshakeRecordContent)
|
ClientHelloHandshakeRecordContent clientHello = (ClientHelloHandshakeRecordContent)
|
||||||
getHandshake(tlsPackets.values(), HandshakeType.CLIENT_HELLO).orElseThrow();
|
getHandshake(tlsPackets.values(), HandshakeType.CLIENT_HELLO).orElseThrow();
|
||||||
@@ -65,10 +62,18 @@ public class TlsDecryptor {
|
|||||||
|
|
||||||
if (cipherSuite.name().startsWith("TLS_RSA_WITH_")) {
|
if (cipherSuite.name().startsWith("TLS_RSA_WITH_")) {
|
||||||
Matcher matcher = cipherSuitePattern.matcher(cipherSuite.name());
|
Matcher matcher = cipherSuitePattern.matcher(cipherSuite.name());
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
matcher.find();
|
matcher.find();
|
||||||
String blockCipher = matcher.group(1);
|
String blockCipher = matcher.group(1);
|
||||||
String hashAlgo = matcher.group(2);
|
String hashAlgo = matcher.group(2);
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
RSAPrivateKey privateKey = keysHolder.getKey(null);
|
||||||
|
if(privateKey == null) {
|
||||||
|
log.warn("Key for modulus not found: {}", "TODO");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BasicRecordContent clientKeyExchange = (BasicRecordContent)
|
BasicRecordContent clientKeyExchange = (BasicRecordContent)
|
||||||
getHandshake(tlsPackets.values(), HandshakeType.CLIENT_KEY_EXCHANGE).orElseThrow();
|
getHandshake(tlsPackets.values(), HandshakeType.CLIENT_KEY_EXCHANGE).orElseThrow();
|
||||||
|
|
||||||
@@ -83,7 +88,8 @@ public class TlsDecryptor {
|
|||||||
BcTlsSecret preSecret = new BcTlsSecret(new BcTlsCrypto(null), preMaster);
|
BcTlsSecret preSecret = new BcTlsSecret(new BcTlsCrypto(null), preMaster);
|
||||||
TlsSecret masterSecret = preSecret.deriveUsingPRF(
|
TlsSecret masterSecret = preSecret.deriveUsingPRF(
|
||||||
PRFAlgorithm.tls_prf_sha256, ExporterLabel.master_secret, randomCS, 48);
|
PRFAlgorithm.tls_prf_sha256, ExporterLabel.master_secret, randomCS, 48);
|
||||||
byte[] expanded = masterSecret.deriveUsingPRF(PRFAlgorithm.tls_prf_sha256, ExporterLabel.key_expansion, randomSC, 136).extract(); // для sha256
|
byte[] expanded = masterSecret.deriveUsingPRF(
|
||||||
|
PRFAlgorithm.tls_prf_sha256, ExporterLabel.key_expansion, randomSC, 136).extract(); // для sha256
|
||||||
|
|
||||||
byte[] clientMacKey = new byte[20];
|
byte[] clientMacKey = new byte[20];
|
||||||
byte[] serverMacKey = new byte[20];
|
byte[] serverMacKey = new byte[20];
|
||||||
@@ -100,33 +106,77 @@ public class TlsDecryptor {
|
|||||||
bb.get(clientIV);
|
bb.get(clientIV);
|
||||||
bb.get(serverIV);
|
bb.get(serverIV);
|
||||||
|
|
||||||
Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding"); // TLS_RSA_WITH_AES_256_CBC_SHA
|
byte[] clientFinishedEncrypted = getFinishedData(tlsPackets, true);
|
||||||
SecretKeySpec skeySpec = new SecretKeySpec(clientEncryptionKey, "AES");
|
byte[] serverFinishedEncrypted = getFinishedData(tlsPackets, false);
|
||||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(clientIV);
|
|
||||||
aes.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
|
|
||||||
|
|
||||||
byte[] data = tlsPackets.entrySet().stream()
|
Cipher clientCipher = createCipher(clientEncryptionKey, clientIV, clientFinishedEncrypted);
|
||||||
.filter(ent -> ent.getKey().isIncoming())
|
// byte[] clientFinishedData = clientCipher.update(clientFinishedEncrypted);
|
||||||
.map(Map.Entry::getValue)
|
// HandshakeRecord clientFinished = HandshakeRecord.newInstance(clientFinishedData, 16, clientFinishedData.length - 16);
|
||||||
.flatMap(Collection::stream)
|
|
||||||
.filter(p -> p.getContentType() == ContentType.HANDSHAKE)
|
|
||||||
.map(p -> ((HandshakeRecord) p.getRecord()))
|
|
||||||
.filter(r -> r.getHandshakeType() == HandshakeType.ENCRYPTED_HANDSHAKE_MESSAGE)
|
|
||||||
.map(r -> ((BasicRecordContent) r.getContent()))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow()
|
|
||||||
.getContent();
|
|
||||||
|
|
||||||
byte[] decrypt = aes.doFinal(data);
|
Cipher serverCipher = createCipher(serverEncryptionKey, serverIV, serverFinishedEncrypted);
|
||||||
System.out.println();
|
// byte[] serverFinishedData = serverCipher.update(serverFinishedEncrypted);
|
||||||
|
// HandshakeRecord serverFinished = HandshakeRecord.newInstance(serverFinishedData, 16, serverFinishedData.length - 16);
|
||||||
|
|
||||||
|
for (Map.Entry<Packet, TlsPacket.TlsHeader> entry : tlsPackets.entries()) {
|
||||||
|
if (entry.getValue().getContentType() == ContentType.APPLICATION_DATA) {
|
||||||
|
byte[] data = ((ApplicationDataRecord) entry.getValue().getRecord()).getData();
|
||||||
|
boolean client = entry.getKey().isIncoming();
|
||||||
|
|
||||||
|
byte[] decoded;
|
||||||
|
|
||||||
|
if(client) {
|
||||||
|
decoded = clientCipher.update(data);
|
||||||
|
} else {
|
||||||
|
decoded = serverCipher.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded = clearDecodedData(decoded);
|
||||||
|
String string = new String(decoded);
|
||||||
|
System.out.println(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<HandshakeRecordContent> getHandshake(Collection<List<TlsPacket.TlsHeader>> packets,
|
@SneakyThrows
|
||||||
|
private Cipher createCipher(byte[] key, byte[] iv, byte[] initData) {
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // TLS_RSA_WITH_AES_256_CBC_SHA
|
||||||
|
SecretKeySpec serverSkeySpec = new SecretKeySpec(key, "AES");
|
||||||
|
IvParameterSpec serverIvParameterSpec = new IvParameterSpec(iv);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, serverSkeySpec, serverIvParameterSpec);
|
||||||
|
cipher.update(initData);
|
||||||
|
|
||||||
|
return cipher;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] clearDecodedData(byte[] decoded) {
|
||||||
|
int start = 32;
|
||||||
|
int end = decoded.length - 6; //FIXME
|
||||||
|
decoded = ByteArrays.getSubArray(decoded, start, end - start);
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getFinishedData(ListMultimap<Packet, TlsPacket.TlsHeader> tlsPackets, boolean incoming) {
|
||||||
|
return ((BasicRecordContent) getHandshake(tlsPackets.asMap().entrySet().stream()
|
||||||
|
.filter(ent -> ent.getKey().isIncoming() == incoming)
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.flatMap(Collection::stream), HandshakeType.ENCRYPTED_HANDSHAKE_MESSAGE))
|
||||||
|
.getContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HandshakeRecordContent getHandshake(Stream<TlsPacket.TlsHeader> stream, HandshakeType handshakeType) {
|
||||||
|
return stream.filter(p -> p.getContentType() == ContentType.HANDSHAKE)
|
||||||
|
.map(p -> ((HandshakeRecord) p.getRecord()))
|
||||||
|
.filter(r -> r.getHandshakeType() == handshakeType)
|
||||||
|
.map(r -> ((BasicRecordContent) r.getContent()))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<HandshakeRecordContent> getHandshake(Collection<TlsPacket.TlsHeader> packets,
|
||||||
HandshakeType handshakeType) {
|
HandshakeType handshakeType) {
|
||||||
return packets.stream()
|
return packets.stream()
|
||||||
.flatMap(Collection::stream)
|
|
||||||
.filter(p -> p.getContentType() == ContentType.HANDSHAKE)
|
.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)
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package ru.serega6531.packmate;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import ru.serega6531.packmate.model.Packet;
|
import ru.serega6531.packmate.model.Packet;
|
||||||
|
import ru.serega6531.packmate.service.optimization.RsaKeysHolder;
|
||||||
import ru.serega6531.packmate.service.optimization.TlsDecryptor;
|
import ru.serega6531.packmate.service.optimization.TlsDecryptor;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -13,7 +15,12 @@ public class TlsDecryptorTest {
|
|||||||
public void testDecryptTls() throws IOException {
|
public void testDecryptTls() throws IOException {
|
||||||
List<Packet> packets = new PackmateDumpFileLoader("tls.pkmt").getPackets();
|
List<Packet> packets = new PackmateDumpFileLoader("tls.pkmt").getPackets();
|
||||||
|
|
||||||
TlsDecryptor decryptor = new TlsDecryptor(packets);
|
RsaKeysHolder keysHolder = new RsaKeysHolder();
|
||||||
|
File pemFile = new File(getClass().getClassLoader().getResource("tls.pem").getFile());
|
||||||
|
File keyFile = new File(getClass().getClassLoader().getResource("tls.key").getFile());
|
||||||
|
keysHolder.addKey(pemFile, keyFile);
|
||||||
|
|
||||||
|
TlsDecryptor decryptor = new TlsDecryptor(packets, keysHolder);
|
||||||
decryptor.decryptTls();
|
decryptor.decryptTls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,4 +9,8 @@ out
|
|||||||
in
|
in
|
||||||
17030302b00ac07f953e2f4e10a46082de38b31b9a45e70f008e545d48da877ce854238fe9b5f32dfde15b51c1e0c92410a169bb015287d92771ca2f8e64bcaec6da2ee03e793298a8f67ff5892e228dcac6d0d5c7e76e2ee98aaf394bd728a8d791b082bd05b6f4dce8d9d78e29fcf201c54d1cc721e7cfeeb3d9e0ee1d09acf03f6cd39a4a9581fa2cc01e81482daf39988f6ac451eaec4556827d8e928ddb5e761f5b005bacde9c129db4d0ae068063ae6cf24775a57c37438275a6dfab4621436617b3a197a958d01c60c6db21fec6f0ffd19a66bba730f3f91da0dd99407d17a03a9a0dcc6cac6bd89e1ad3e47b0e52f4c6e21b603d7843ef852526e597ef07a045b7c5ec9b2468e11a465e32b4349b17d2ac90c683d0fd510f81c53879679da22355eb4fae89574843941e3993e530ce956efc3b50807fa687912a4c3b5a087a926a41c49993c8da60f7873a41186eae562e8a9ec7367e6808f4cc83f5e67b0fc79e2efc4e5b734a519f2aa7b3dfb89dd848c0da255d3f20f6d169e8566788c38ef54b543ae41073123d44474e514b883f956ee1330792cab686db3e95363123dfa0b4246e139a365784d56c5bbd6db9a8099c5117487b8b1c313741921784c4b399be18a59bd98d729f9d048ecf2f0dae6c782a2d6ed8b45dfe5f47388d8da99b213e26a6a284ff1758ada6bdddbb991b62b410415bd38f823f57f83dafaa177ac86e68bfc17de4d7cf4333bf5098947913072491e9c3341ae1b95c8710b90a3dafc55f0643e8d240dd79259958c115b15520a98cdf7a43b3a7c6647aadf417bdacb2e7560763cdfa827ad5ce6846d267af4730dd221c9ac1e4adb6f47648af732bd88ecc6da2c13e0bd6881ee16fcc34830928737a52614fc80b6ceb7dd5dfffe95c377a999eb3505a9b82c13ae4da71d21bbb33583b12663364a3538c77df683adc78936ba525dd7c0e2fa662e505a2df
|
17030302b00ac07f953e2f4e10a46082de38b31b9a45e70f008e545d48da877ce854238fe9b5f32dfde15b51c1e0c92410a169bb015287d92771ca2f8e64bcaec6da2ee03e793298a8f67ff5892e228dcac6d0d5c7e76e2ee98aaf394bd728a8d791b082bd05b6f4dce8d9d78e29fcf201c54d1cc721e7cfeeb3d9e0ee1d09acf03f6cd39a4a9581fa2cc01e81482daf39988f6ac451eaec4556827d8e928ddb5e761f5b005bacde9c129db4d0ae068063ae6cf24775a57c37438275a6dfab4621436617b3a197a958d01c60c6db21fec6f0ffd19a66bba730f3f91da0dd99407d17a03a9a0dcc6cac6bd89e1ad3e47b0e52f4c6e21b603d7843ef852526e597ef07a045b7c5ec9b2468e11a465e32b4349b17d2ac90c683d0fd510f81c53879679da22355eb4fae89574843941e3993e530ce956efc3b50807fa687912a4c3b5a087a926a41c49993c8da60f7873a41186eae562e8a9ec7367e6808f4cc83f5e67b0fc79e2efc4e5b734a519f2aa7b3dfb89dd848c0da255d3f20f6d169e8566788c38ef54b543ae41073123d44474e514b883f956ee1330792cab686db3e95363123dfa0b4246e139a365784d56c5bbd6db9a8099c5117487b8b1c313741921784c4b399be18a59bd98d729f9d048ecf2f0dae6c782a2d6ed8b45dfe5f47388d8da99b213e26a6a284ff1758ada6bdddbb991b62b410415bd38f823f57f83dafaa177ac86e68bfc17de4d7cf4333bf5098947913072491e9c3341ae1b95c8710b90a3dafc55f0643e8d240dd79259958c115b15520a98cdf7a43b3a7c6647aadf417bdacb2e7560763cdfa827ad5ce6846d267af4730dd221c9ac1e4adb6f47648af732bd88ecc6da2c13e0bd6881ee16fcc34830928737a52614fc80b6ceb7dd5dfffe95c377a999eb3505a9b82c13ae4da71d21bbb33583b12663364a3538c77df683adc78936ba525dd7c0e2fa662e505a2df
|
||||||
out
|
out
|
||||||
170303011072181c58ad94344f833a3c6517232928ff5614ef47044478a71d54c4de8a6e9edc2d0808128d6b6440230c6cfecc653e3e02536f9bd7bcae8cb0668627147ba3b548725a3549dc31a5b69cb15654e692610d8472be09c083d47a7ef0dd4ea464845e62c9fd2b88def3c3feb2367309c4d2440d7bd3d89b26ae67c947c9887257462bc7f5e5088bbe15b132fe01e5eabc8cd60ae31db08046d5b0dbc4ac1705c93b7c74ce741d4e52a5c8591e214877f38bc0b9216a4bd8527ff10878b5f8cec4d37427c021fad6de75f643e6b83466a5833493e6bab8e07e5b6e73ad3b8a3171ddd1dc91a709476eb90d40e1994c3b7d2d8ddde97c23fff4fbb34435d90bd68f8f6b645c80e9bd5d0dba6d36ecf2d420
|
170303011072181c58ad94344f833a3c6517232928ff5614ef47044478a71d54c4de8a6e9edc2d0808128d6b6440230c6cfecc653e3e02536f9bd7bcae8cb0668627147ba3b548725a3549dc31a5b69cb15654e692610d8472be09c083d47a7ef0dd4ea464845e62c9fd2b88def3c3feb2367309c4d2440d7bd3d89b26ae67c947c9887257462bc7f5e5088bbe15b132fe01e5eabc8cd60ae31db08046d5b0dbc4ac1705c93b7c74ce741d4e52a5c8591e214877f38bc0b9216a4bd8527ff10878b5f8cec4d37427c021fad6de75f643e6b83466a5833493e6bab8e07e5b6e73ad3b8a3171ddd1dc91a709476eb90d40e1994c3b7d2d8ddde97c23fff4fbb34435d90bd68f8f6b645c80e9bd5d0dba6d36ecf2d420
|
||||||
|
in
|
||||||
|
1703030250f6ec86ac5c98a6a04d7af7093380c07da57e695d6d00aca7c04dfd0ec4c7037de18370fec2a4cca0944e5f6f05c71310866d0e051a6cacf05aa974e7ba0c1c0246e7f80f8f88782134e027a77f5ac1c2429992bf767f24a3ea62290acea854f640254572d63356509e13913032a5c2bf47c9ff21582935509c2c411d3062dc4c9ac3ec1bdfeb811a4bf941b8e14654c8a59ec2d3dfa79ca6af286071176fca09daeaac644b8f4668b477195cb55e43651d0e17432dc9d4d905bf4df98f543470faa59776216eeb24939476536e650365c97faea4e1c238c4f019f4e7b47bc2e10badd8eddb54223a3723199f5acbf1c6b711cbba1824d605c4f4bf5d1bacc5403b9dd31b713977b5b09bdd37613883fcd9466f51a0f30100037217cf30c0d9660d031d047115308969d10cc4f694cbe6d5acbaf414906f34740a5d22954fb084d501d96a7410ed874b345193fb0c1e23acd994b6cae4c06a8c68c7bea4f617d20b8ab3df57fc02cf045770b3fc152f626b6e14575a0dd13f1259b1e63d5209e00a296f3a0374cbdc21730430b6422d4ea8e3388b2a5f81e889f915146526f6a38449e369381f2acd120d8a01aeedb41b9eb951e922d12ddd080ced1a7b143bb92344f7b8e645054ed4ac2e5c6457bc3f73963121646f5ed69ea961bdb4303e13be2c352461d48869b5d12019e109e263e56f22bb7fe8f2bd78b89c88a9d7dd014e9e5ac79669a8ec6885779a94663e77a13792637e0f2f3b2535cfb30cbe4e994d05101a321dffa355cd6c34b8f38f159e743325634b0181e5016292d22e0d493ab028ae183afe7b10b8bb52281c7e1d
|
||||||
|
out
|
||||||
|
17030300e06546909140faad74b8c74145f1e8b239d54e73a8cdb7484f8cf272b1d5fe6e55ff64e284b4c5d52e3ce27a5bf2b6f7e3e6593b47041761f622e8c7016efdc5a3ca9e5f343a5564d3201fa80f980dbb02154aaab808fb0bfe612aaa2d56385600b6957e87ab8e7b85ae5e55591db9218217d47e1b4d6950752e72b3a92bc252dd92db70b431277f5100f02939e89a0d16b2e7532253afa86be8821ab69d187d0c93f04b9d50e86339f4f599088b68d82e23f8b032cd3d5ffd3d03664bddd98f917c2470634f1454973765b066dda41edd87514bff3187103cede2a78e9807943f
|
||||||
Reference in New Issue
Block a user