From 9a13b566cff7ab84e4dc37ed446b111794368a4a Mon Sep 17 00:00:00 2001 From: Tim203 Date: Sat, 30 Nov 2019 21:30:25 +0100 Subject: [PATCH] Little changes --- common/pom.xml | 6 ++ .../geysermc/floodgate/util/BedrockData.java | 35 +++++++++ .../floodgate/util/EncryptionUtil.java | 76 +++++++++++++++++++ connector/pom.xml | 6 -- 4 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 common/src/main/java/org/geysermc/floodgate/util/BedrockData.java create mode 100644 common/src/main/java/org/geysermc/floodgate/util/EncryptionUtil.java diff --git a/common/pom.xml b/common/pom.xml index 6a0a6ff0..d54730ff 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -10,6 +10,12 @@ common + + org.projectlombok + lombok + 1.18.4 + providec + com.github.steveice10 opennbt diff --git a/common/src/main/java/org/geysermc/floodgate/util/BedrockData.java b/common/src/main/java/org/geysermc/floodgate/util/BedrockData.java new file mode 100644 index 00000000..f4efa971 --- /dev/null +++ b/common/src/main/java/org/geysermc/floodgate/util/BedrockData.java @@ -0,0 +1,35 @@ +package org.geysermc.floodgate.util; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class BedrockData { + public static final int EXPECTED_LENGTH = 6; + private String version; + private String username; + private String xuid; + private int deviceId; + private String languageCode; + private int inputMode; + private int dataLength; + + public BedrockData(String version, String username, String xuid, int deviceId, String languageCode, int inputMode) { + this(version, username, xuid, deviceId, languageCode, inputMode, EXPECTED_LENGTH); + } + + public static BedrockData fromString(String data) { + String[] split = data.split("\0"); + if (split.length != EXPECTED_LENGTH) return null; + return new BedrockData(split[0], split[1], split[2], Integer.parseInt(split[3]), split[4], Integer.parseInt(split[5]), split.length); + } + + public static BedrockData fromRawData(byte[] data) { + return fromString(new String(data)); + } + + public String toString() { + return version +'\0'+ username +'\0'+ xuid +'\0'+ deviceId +'\0'+ languageCode +'\0'+ inputMode; + } +} diff --git a/common/src/main/java/org/geysermc/floodgate/util/EncryptionUtil.java b/common/src/main/java/org/geysermc/floodgate/util/EncryptionUtil.java new file mode 100644 index 00000000..881d01ba --- /dev/null +++ b/common/src/main/java/org/geysermc/floodgate/util/EncryptionUtil.java @@ -0,0 +1,76 @@ +package org.geysermc.floodgate.util; + +import javax.crypto.*; +import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.*; +import java.security.spec.EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +public class EncryptionUtil { + public static String encrypt(Key key, String data) throws IllegalBlockSizeException, + InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException { + KeyGenerator generator = KeyGenerator.getInstance("AES"); + generator.init(128); + SecretKey secretKey = generator.generateKey(); + + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + byte[] encryptedText = cipher.doFinal(data.getBytes()); + + cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(key instanceof PublicKey ? Cipher.PUBLIC_KEY : Cipher.PRIVATE_KEY, key); + return Base64.getEncoder().encodeToString(cipher.doFinal(secretKey.getEncoded())) + '\0' + + Base64.getEncoder().encodeToString(encryptedText); + } + + public static String encryptBedrockData(Key key, BedrockData data) throws IllegalBlockSizeException, + InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException { + return encrypt(key, data.toString()); + } + + public static byte[] decrypt(Key key, String encryptedData) throws IllegalBlockSizeException, + InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException { + String[] split = encryptedData.split("\0"); + if (split.length != 2) { + throw new IllegalArgumentException("Expected two arguments, got " + split.length); + } + + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(key instanceof PublicKey ? Cipher.PUBLIC_KEY : Cipher.PRIVATE_KEY, key); + byte[] decryptedKey = cipher.doFinal(Base64.getDecoder().decode(split[0])); + + SecretKey secretKey = new SecretKeySpec(decryptedKey, 0, decryptedKey.length, "AES"); + cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, secretKey); + return cipher.doFinal(Base64.getDecoder().decode(split[1])); + } + + public static BedrockData decryptBedrockData(Key key, String encryptedData) throws IllegalBlockSizeException, + InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException { + return BedrockData.fromRawData(decrypt(key, encryptedData)); + } + + @SuppressWarnings("unchecked") + public static T getKeyFromFile(Path fileLocation, Class keyType) throws + IOException, InvalidKeySpecException, NoSuchAlgorithmException { + boolean isPublicKey = keyType == PublicKey.class; + if (!isPublicKey && keyType != PrivateKey.class) { + throw new RuntimeException("I can only read public and private keys!"); + } + + byte[] key = Files.readAllBytes(fileLocation); + + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + EncodedKeySpec keySpec = isPublicKey ? new X509EncodedKeySpec(key) : new PKCS8EncodedKeySpec(key); + return (T) (isPublicKey ? + keyFactory.generatePublic(keySpec) : + keyFactory.generatePrivate(keySpec) + ); + } +} diff --git a/connector/pom.xml b/connector/pom.xml index 5b4a2bcf..60ecfc55 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -22,12 +22,6 @@ 1.0-SNAPSHOT compile - - org.geysermc - floodgate-common - 1.0-SNAPSHOT - compile - com.fasterxml.jackson.dataformat jackson-dataformat-yaml