diff --git a/pom.xml b/pom.xml index d654b90..c97c3bb 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ 8 8 + 1.7.10 @@ -34,6 +35,51 @@ + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + process-sources + + compile + + + + src/main/java + src/main/kotlin + src/main/resources + + + + + test-compile + process-test-sources + + test-compile + + + + src/test/java + src/test/kotlin + src/test/resources + + + + + + 1.8 + + + org.projectlombok + lombok + 1.18.20 + + + + org.apache.maven.plugins maven-compiler-plugin @@ -83,6 +129,17 @@ 1.18.24 provided + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-test + ${kotlin.version} + test + org.github.spigot 1.13 diff --git a/src/main/java/dev/brighten/ac/Anticheat.java b/src/main/java/dev/brighten/ac/Anticheat.java index 8f33cc5..a8d095e 100644 --- a/src/main/java/dev/brighten/ac/Anticheat.java +++ b/src/main/java/dev/brighten/ac/Anticheat.java @@ -27,6 +27,7 @@ import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.world.WorldInfo; import dev.brighten.loader.LoaderPlugin; +import dev.brighten.log.socket.LogSocketManager; import lombok.Getter; import lombok.experimental.PackagePrivate; import org.bukkit.Bukkit; @@ -61,6 +62,7 @@ public class Anticheat extends LoaderPlugin { private KeepaliveProcessor keepaliveProcessor; private PacketHandler packetHandler; private LoggerManager logManager; + public LogSocketManager socketManager; private int currentTick; private Deque onTickEnd = new LinkedList<>(); private ServerInjector injector; @@ -116,6 +118,8 @@ public class Anticheat extends LoaderPlugin { this.checkManager = new CheckManager(); this.playerRegistry = new PlayerRegistry(); this.packetHandler = new PacketHandler(); + this.socketManager = new LogSocketManager(); + socketManager.startSockets(); logManager = new LoggerManager(); keepaliveProcessor.start(); @@ -154,6 +158,8 @@ public class Anticheat extends LoaderPlugin { ProtocolAPI.INSTANCE = null; tps = null; + socketManager.shutdownSockets(); + logManager.shutDown(); Bukkit.getScheduler().cancelTasks(getPluginInstance()); diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java index 4d709fa..e9a3c3a 100644 --- a/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java @@ -262,7 +262,10 @@ public class Horizontal extends Check { } else debug("bad movement"); } else if (buffer > 0) buffer -= 0.05f; - debug("smallest=%s efcs=[%s] pm=%.5f dxz=%.5f b=%.1f", smallestDelta, player.getPotionHandler().potionEffects.stream().map(pe -> pe.getType().getName() + ";" + pe.getAmplifier()).collect(Collectors.joining(", ")), pmotion, + debug("smallest=%s sp=%s efcs=[%s] pm=%.5f dxz=%.5f b=%.1f", smallestDelta, + player.getInfo().isSprinting(), player.getPotionHandler().potionEffects.stream() + .map(pe -> pe.getType().getName() + ";" + pe.getAmplifier()) + .collect(Collectors.joining(", ")), pmotion, player.getMovement().getDeltaXZ(), buffer); } lastLastClientGround = player.getMovement().getFrom().isOnGround(); diff --git a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java index caf18ad..7e42890 100644 --- a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java +++ b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java @@ -185,7 +185,7 @@ public class AnticheatCommand extends BaseCommand { return crc.getValue(); } - private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(3912178420L)); + private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(3912178420L, 2719903731L)); @Subcommand("alerts") @CommandPermission("anticheat.command.alerts") diff --git a/src/main/java/dev/brighten/ac/data/PlayerRegistry.java b/src/main/java/dev/brighten/ac/data/PlayerRegistry.java index 6b5232c..b208af6 100644 --- a/src/main/java/dev/brighten/ac/data/PlayerRegistry.java +++ b/src/main/java/dev/brighten/ac/data/PlayerRegistry.java @@ -105,7 +105,7 @@ public class PlayerRegistry { return crc.getValue(); } - private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(3912178420L)); + private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(3912178420L, 2719903731L)); public Optional getPlayer(UUID uuid) { return Optional.ofNullable(aplayerMap.get(uuid.hashCode())); diff --git a/src/main/java/dev/brighten/ac/logging/LoggerManager.java b/src/main/java/dev/brighten/ac/logging/LoggerManager.java index debf30f..ce30502 100644 --- a/src/main/java/dev/brighten/ac/logging/LoggerManager.java +++ b/src/main/java/dev/brighten/ac/logging/LoggerManager.java @@ -3,22 +3,27 @@ package dev.brighten.ac.logging; import dev.brighten.ac.Anticheat; import dev.brighten.ac.check.CheckData; import dev.brighten.ac.data.APlayer; -import dev.brighten.ac.logging.sql.ExecutableStatement; -import dev.brighten.ac.logging.sql.MySQL; import dev.brighten.ac.logging.sql.Query; import dev.brighten.ac.logging.sql.ResultSetIterator; +import dev.brighten.ac.utils.RunUtils; +import dev.brighten.log.socket.OutRequest; +import dev.brighten.log.socket.RequestType; +import dev.brighten.log.utils.EncryptionUtils; -import java.sql.Timestamp; -import java.util.ArrayList; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.security.KeyPair; +import java.security.PublicKey; +import java.util.Base64; import java.util.Deque; import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.TimeUnit; public class LoggerManager { private final Deque logList = new LinkedList<>(); + private KeyPair keys; + private PublicKey encryptKey; /* * Structure of Log @@ -26,57 +31,68 @@ public class LoggerManager { */ public void init() { // Starting up H2 - MySQL.initH2(); + Anticheat.INSTANCE.getLogger().info("Generating RSA..."); + keys = EncryptionUtils.Companion.geneateRsa(); + try { + Anticheat.INSTANCE.getLogger().info("Sending init request to log server..."); + OutRequest request = new OutRequest(RequestType.INITIALIZE.toString(), "localhost", null); - Query.prepare("CREATE TABLE IF NOT EXISTS `logs` (" + - "`id` INT NOT NULL AUTO_INCREMENT," + - "`uuid` INT NOT NULL," + - "`check` VARCHAR(32) NOT NULL," + - "`vl` FLOAT NOT NULL," + - "`data` MEDIUMTEXT NOT NULL," + - "`time` TIMESTAMP NOT NULL," + - "PRIMARY KEY (`id`)" + - ");").execute(); + String encoded = Base64.getEncoder().encodeToString(keys.getPublic().getEncoded()); + System.out.println(encoded); + request.getObjects().writeUTF(encoded); - Query.prepare("create index if not exists `uuid_1` on `logs` (`uuid`)") - .execute(); - Query.prepare("create index if not exists `uuid_check_1` on `logs` (`uuid`, `check`)") - .execute(); + request.write(); - Anticheat.INSTANCE.getScheduler().scheduleAtFixedRate(() -> { - if(logList.size() > 0) { - synchronized (logList) { - final StringBuilder values = new StringBuilder(); + Anticheat.INSTANCE.getLogger().info("Sent!"); + } catch (IOException e) { + throw new RuntimeException(e); + } - List objectsToInsert = new ArrayList<>(); - Log log = null; - int amount = 0; - while((log = logList.poll()) != null) { - objectsToInsert.add(log.getUuid().hashCode()); - objectsToInsert.add(log.getCheckId()); - objectsToInsert.add(log.getVl()); - objectsToInsert.add(log.getData()); - objectsToInsert.add(new Timestamp(log.getTime())); + Anticheat.INSTANCE.getSocketManager().onInputReceived(event -> { + if(event.getRequest().getHeader().equals(RequestType.INITIALIZE.toString())) { + System.out.println("Received key from server!"); + ObjectInputStream objectStream = event.getRequest().getObjects(); + try { + String publicKeyString = objectStream.readUTF(); - if(++amount >= 150) break; - } - - for (int i = 0; i < amount; i++) { - values.append(i > 0 ? "," : "").append("(?, ?, ?, ?, ?)"); - } - - ExecutableStatement statement = Query.prepare("INSERT INTO `logs` " + - "(`uuid`,`check`,`vl`,`data`,`time`) VALUES" + values.toString()) - .append(objectsToInsert.toArray()); - - statement.execute(); - - Anticheat.INSTANCE.getLogger().info("Saved " + amount + " logs!"); - - objectsToInsert.clear(); + encryptKey = EncryptionUtils.Companion.publicKeyFromString(publicKeyString); + } catch (IOException e) { + throw new RuntimeException(e); } } - }, 5, 10, TimeUnit.SECONDS); + }); + + RunUtils.taskTimerAsync(() -> { + System.out.println("Running ping!"); + + OutRequest request = new OutRequest(RequestType.PING.toString(), + "localhost", + encryptKey); + + try { + request.getObjects().writeLong(System.currentTimeMillis()); + request.write(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }, 80, 40); + + Anticheat.INSTANCE.socketManager.onInputReceived(event -> { + if(event.getRequest().getHeader().equals(RequestType.PING.toString())) { + ObjectInputStream objects = event.getRequest().getObjects(keys.getPrivate()); + + try { + long serverTime = objects.readLong(); + long extense = objects.readLong(); + + long ping = System.currentTimeMillis() - serverTime + extense; + + System.out.println("Ping: " + ping + "ms"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); } public void insertLog(APlayer player, CheckData checkData, float vl, long time, String data) { @@ -94,6 +110,6 @@ public class LoggerManager { } public void shutDown() { - MySQL.shutdown(); + } } diff --git a/src/main/java/dev/brighten/ac/utils/Base64.java b/src/main/java/dev/brighten/ac/utils/Base64.java new file mode 100644 index 0000000..cc86cfb --- /dev/null +++ b/src/main/java/dev/brighten/ac/utils/Base64.java @@ -0,0 +1,92 @@ +package dev.brighten.ac.utils; + +public final class Base64 { + private static final int BYTES_PER_UNENCODED_BLOCK = 3; + private static final int BYTES_PER_ENCODED_BLOCK = 4; + private static final int SIX_BIT_MASK = 63; + private static final byte PAD = 61; + private static final byte[] ENCODE_TABLE = new byte[]{65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47}; + private static final int[] DECODE_TABLE = new int[128]; + + public static byte[] decode(String s) { + int delta = s.endsWith("==") ? 2 : (s.endsWith("=") ? 1 : 0); + byte[] buffer = new byte[s.length() * 3 / 4 - delta]; + int mask = 255; + int pos = 0; + + for(int i = 0; i < s.length(); i += 4) { + int c0 = DECODE_TABLE[s.charAt(i)]; + int c1 = DECODE_TABLE[s.charAt(i + 1)]; + buffer[pos++] = (byte)((c0 << 2 | c1 >> 4) & mask); + if (pos >= buffer.length) { + return buffer; + } + + int c2 = DECODE_TABLE[s.charAt(i + 2)]; + buffer[pos++] = (byte)((c1 << 4 | c2 >> 2) & mask); + if (pos >= buffer.length) { + return buffer; + } + + int c3 = DECODE_TABLE[s.charAt(i + 3)]; + buffer[pos++] = (byte)((c2 << 6 | c3) & mask); + } + + return buffer; + } + + public static String encode(byte[] in) { + int modulus = 0; + int bitWorkArea = 0; + int numEncodedBytes = in.length / 3 * 4 + (in.length % 3 == 0 ? 0 : 4); + byte[] buffer = new byte[numEncodedBytes]; + int pos = 0; + byte[] var6 = in; + int var7 = in.length; + + for(int var8 = 0; var8 < var7; ++var8) { + int b = var6[var8]; + modulus = (modulus + 1) % 3; + if (b < 0) { + b += 256; + } + + bitWorkArea = (bitWorkArea << 8) + b; + if (0 == modulus) { + buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 18 & 63]; + buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 12 & 63]; + buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 6 & 63]; + buffer[pos++] = ENCODE_TABLE[bitWorkArea & 63]; + } + } + + switch (modulus) { + case 1: + buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 2 & 63]; + buffer[pos++] = ENCODE_TABLE[bitWorkArea << 4 & 63]; + buffer[pos++] = 61; + buffer[pos] = 61; + break; + case 2: + buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 10 & 63]; + buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 4 & 63]; + buffer[pos++] = ENCODE_TABLE[bitWorkArea << 2 & 63]; + buffer[pos] = 61; + } + + return byteArrayToString(buffer); + } + + private static String byteArrayToString(byte[] buffer) { + return new String(buffer, 0, 0, buffer.length); + } + + private Base64() { + } + + static { + for(int i = 0; i < ENCODE_TABLE.length; DECODE_TABLE[ENCODE_TABLE[i]] = i++) { + } + + } +} diff --git a/src/main/java/dev/brighten/ac/utils/IntegrityCheck.java b/src/main/java/dev/brighten/ac/utils/IntegrityCheck.java index dc39fc5..0af69cf 100644 --- a/src/main/java/dev/brighten/ac/utils/IntegrityCheck.java +++ b/src/main/java/dev/brighten/ac/utils/IntegrityCheck.java @@ -92,7 +92,7 @@ public class IntegrityCheck { return crc.getValue(); } - private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(3912178420L)); + private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(3912178420L, 2719903731L)); } diff --git a/src/main/java/dev/brighten/ac/utils/StreamUtils.java b/src/main/java/dev/brighten/ac/utils/StreamUtils.java new file mode 100644 index 0000000..d3b90f3 --- /dev/null +++ b/src/main/java/dev/brighten/ac/utils/StreamUtils.java @@ -0,0 +1,50 @@ +package dev.brighten.ac.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +public class StreamUtils { + public static void streamCopy(InputStream in, OutputStream out) throws IOException { + assert (in != null); + assert (out != null); + ReadableByteChannel inChannel = Channels.newChannel(in); + WritableByteChannel outChannel = Channels.newChannel(out); + channelCopy(inChannel, outChannel); + } + + /** + * A fast method to copy bytes from one channel to another; uses direct 16k + * buffers to minimize copies and OS overhead. + * @author http://thomaswabner.wordpress.com/2007/10/09/fast-stream-copy-using-javanio-channels/ + * @param src - a non-null readable bytechannel to read the data from + * @param dest - a non-null writeable byte channel to write the data to + */ + public static void channelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException { + assert (src != null); + assert (dest != null); + final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024); + while (src.read(buffer) != -1) { + // prepare the buffer to be drained + buffer.flip(); + // write to the channel, may block + dest.write(buffer); + // If partial transfer, shift remainder down + // If buffer is empty, same as doing clear() + buffer.compact(); + } + + // EOF will leave buffer in fill state + buffer.flip(); + + // make sure the buffer is fully drained. + while (buffer.hasRemaining()) { + dest.write(buffer); + } + } + +} diff --git a/src/main/kotlin/dev/brighten/log/socket/InRequest.kt b/src/main/kotlin/dev/brighten/log/socket/InRequest.kt new file mode 100644 index 0000000..af52b72 --- /dev/null +++ b/src/main/kotlin/dev/brighten/log/socket/InRequest.kt @@ -0,0 +1,53 @@ +package dev.brighten.log.socket + +import dev.brighten.log.utils.EncryptionUtils.Companion.decrypt +import lombok.Getter +import java.io.ByteArrayInputStream +import java.io.DataInputStream +import java.io.IOException +import java.io.ObjectInputStream +import java.net.InetAddress +import java.security.PrivateKey +import java.util.* + +@Getter +class InRequest(address: InetAddress, val stream: DataInputStream) { + val header: String + val encrypted: Boolean + var objectString: String? = null + + init { + header = stream.readUTF() + encrypted = stream.readBoolean() + objectString = stream.readUTF(); + } + + val objects: ObjectInputStream + get() { + if (encrypted) throw RuntimeException("Encrypted request. Must decrypt request to be processed.") + return try { + val bytes = Base64.getDecoder().decode(objectString) + ObjectInputStream(ByteArrayInputStream(bytes)) + } catch (e: IOException) { + throw RuntimeException(e) + } + } + + fun getObjects(key: PrivateKey?): ObjectInputStream { + return try { + val bytes = Base64.getDecoder().decode(objectString) + if (!encrypted) { + ObjectInputStream(ByteArrayInputStream(bytes)) + } else { + ObjectInputStream( + ByteArrayInputStream( + Objects + .requireNonNull(decrypt(bytes, key!!)) + ) + ) + } + } catch (e: IOException) { + throw RuntimeException(e) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/brighten/log/socket/LogSocket.kt b/src/main/kotlin/dev/brighten/log/socket/LogSocket.kt new file mode 100644 index 0000000..fc2ac24 --- /dev/null +++ b/src/main/kotlin/dev/brighten/log/socket/LogSocket.kt @@ -0,0 +1,48 @@ +package dev.brighten.log.socket + +import dev.brighten.ac.Anticheat +import java.net.ServerSocket +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors + +class LogSocket(port: Int) { + private val serverSocket: ServerSocket + private var thread: Thread + private var enabled: Boolean = true + private val socketExecutor: ExecutorService; + + init { + socketExecutor = Executors.newCachedThreadPool(); + serverSocket = ServerSocket(port) + thread = Thread { + while (enabled) { + try { + val socket = serverSocket.accept() + socket.soTimeout = 10000 + + Anticheat.INSTANCE.logger.info("Received input on port " + port) + + if(!socket.isClosed) { + try { + System.out.println("executing!") + Anticheat.INSTANCE.socketManager.processInputReceived(socket) + } catch (throwable: Throwable) { + throwable.printStackTrace() + } + } + } catch(e: Throwable) { + e.printStackTrace() + } + } + } + } + + fun startSocket() { + thread.start(); + } + + fun shutdownSocket() { + enabled = false + thread.interrupt() + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/brighten/log/socket/LogSocketManager.kt b/src/main/kotlin/dev/brighten/log/socket/LogSocketManager.kt new file mode 100644 index 0000000..09eecf2 --- /dev/null +++ b/src/main/kotlin/dev/brighten/log/socket/LogSocketManager.kt @@ -0,0 +1,63 @@ +package dev.brighten.log.socket + +import dev.brighten.ac.Anticheat +import dev.brighten.ac.utils.StreamUtils +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.DataInputStream +import java.io.IOException +import java.net.Socket +import java.util.function.Consumer + +class LogSocketManager { + private val inputListeners: MutableList> = ArrayList() + private val sockets: MutableList = ArrayList() + fun startSockets() { + if (sockets.size > 0) { + Anticheat.INSTANCE.logger.warning("Had to shutdown previous sockets when trying to start them!") + sockets.forEach(Consumer { obj: LogSocket -> obj.shutdownSocket() }) + sockets.clear() + } + for (port in allowedPorts) { + val socket = LogSocket(port) + socket.startSocket() + sockets.add(socket) + } + } + + fun shutdownSockets() { + if (sockets.size == 0) { + Anticheat.INSTANCE.logger.warning("No sockets to shutdown!") + return + } + sockets.forEach(Consumer { obj: LogSocket -> obj.shutdownSocket() }) + sockets.clear() + } + + fun onInputReceived(inputReceived: Consumer) { + inputListeners.add(inputReceived) + } + + @Throws(IOException::class) + fun processInputReceived(socket: Socket) { + val stream = socket.getInputStream() + val baos = ByteArrayOutputStream() + StreamUtils.streamCopy(stream, baos); + for (listener in inputListeners) { + val ois = DataInputStream(ByteArrayInputStream(baos.toByteArray())) + val address = socket.inetAddress + + try { + listener.accept(SocketEvent(socket, address, InRequest(address, ois))) + } catch(e: Throwable) { + e.printStackTrace() + } + } + stream.close() + socket.close() + } + + companion object { + private val allowedPorts = intArrayOf(81) + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/brighten/log/socket/OutRequest.kt b/src/main/kotlin/dev/brighten/log/socket/OutRequest.kt new file mode 100644 index 0000000..d7b7339 --- /dev/null +++ b/src/main/kotlin/dev/brighten/log/socket/OutRequest.kt @@ -0,0 +1,49 @@ +package dev.brighten.log.socket + +import dev.brighten.log.utils.EncryptionUtils.Companion.encrypt +import java.io.ByteArrayOutputStream +import java.io.DataOutputStream +import java.io.IOException +import java.io.ObjectOutputStream +import java.net.Socket +import java.security.PublicKey +import java.util.* + +class OutRequest(header: String, ip: String?, key: PublicKey?) { + private val socket: Socket + private var encrypted = false + private val streamToSend: DataOutputStream + private val bytesStream: ByteArrayOutputStream + val objects: ObjectOutputStream + private var key: PublicKey? = null + + init { + socket = Socket(ip, 80) + streamToSend = DataOutputStream(socket.getOutputStream()) + streamToSend.writeUTF(header) + if (key != null) { + encrypted = true + streamToSend.writeBoolean(true) + this.key = key + } else { + encrypted = false + streamToSend.writeBoolean(false) + } + bytesStream = ByteArrayOutputStream() + objects = ObjectOutputStream(bytesStream) + } + + @Throws(IOException::class) + fun write() { + objects.close() + val bytesToWrite = if (encrypted) encrypt(bytesStream.toByteArray(), key!!) else bytesStream.toByteArray(); + try { + val base = Base64.getEncoder().encodeToString(bytesToWrite) + streamToSend.writeUTF(base) + streamToSend.close() + socket.close() + } catch (e: IOException) { + throw RuntimeException(e) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/brighten/log/socket/RequestType.kt b/src/main/kotlin/dev/brighten/log/socket/RequestType.kt new file mode 100644 index 0000000..6c4eead --- /dev/null +++ b/src/main/kotlin/dev/brighten/log/socket/RequestType.kt @@ -0,0 +1,5 @@ +package dev.brighten.log.socket + +enum class RequestType { + INITIALIZE, PING +} \ No newline at end of file diff --git a/src/main/kotlin/dev/brighten/log/socket/SocketEvent.kt b/src/main/kotlin/dev/brighten/log/socket/SocketEvent.kt new file mode 100644 index 0000000..ba8616a --- /dev/null +++ b/src/main/kotlin/dev/brighten/log/socket/SocketEvent.kt @@ -0,0 +1,8 @@ +package dev.brighten.log.socket + +import lombok.Getter +import java.net.InetAddress +import java.net.Socket + +@Getter +class SocketEvent(val socket: Socket, val address: InetAddress, val request: InRequest) \ No newline at end of file diff --git a/src/main/kotlin/dev/brighten/log/utils/EncryptionUtils.kt b/src/main/kotlin/dev/brighten/log/utils/EncryptionUtils.kt new file mode 100644 index 0000000..7f97f2b --- /dev/null +++ b/src/main/kotlin/dev/brighten/log/utils/EncryptionUtils.kt @@ -0,0 +1,57 @@ +package dev.brighten.log.utils + +import java.security.* +import java.security.spec.PKCS8EncodedKeySpec +import java.security.spec.X509EncodedKeySpec +import java.util.* +import javax.crypto.Cipher +import javax.crypto.KeyGenerator +import javax.crypto.SecretKey + +class EncryptionUtils { + companion object { + val rsaGenerator: KeyPairGenerator = KeyPairGenerator.getInstance("RSA"); + val aesGenerator: KeyGenerator = KeyGenerator.getInstance("AES"); + lateinit var skey: SecretKey; + val rsaKeyFactory = KeyFactory.getInstance("RSA"); + + fun geneateRsa(): KeyPair? { + val keyPair = rsaGenerator.genKeyPair(); + return keyPair; + } + + fun encrypt(data: ByteArray, publicKey: PublicKey): ByteArray? { + val cipher: Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + + return cipher.doFinal(data); + } + + fun decrypt(data: ByteArray, privateKey: PrivateKey): ByteArray? { + val cipher: Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + + cipher.init(Cipher.DECRYPT_MODE, privateKey); + + return cipher.doFinal(data); + } + + fun publicKeyFromString(publicKeyString: String): PublicKey? { + val keySpec = X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyString.toByteArray())); + return rsaKeyFactory.generatePublic(keySpec); + } + + fun privateKeyFromString(privateKeyString: String): PrivateKey? { + val keySpec = PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString.toByteArray())); + + return rsaKeyFactory.generatePrivate(keySpec); + } + } + + init { + rsaGenerator.initialize(2048); + + aesGenerator.init(128); + skey = aesGenerator.generateKey(); + } +} \ No newline at end of file