From 977adfc6f08216ba240c9c6d207a8ad37554f5d5 Mon Sep 17 00:00:00 2001 From: syeyoung <42869671+cyoung06@users.noreply.github.com> Date: Wed, 9 Dec 2020 15:11:20 +0900 Subject: read whole jar maybe --- .../kr/syeyoung/dungeonsguide/Authenticator.java | 58 +++++++++++- .../dungeonsguide/customurl/DGURLConnection.java | 102 ++------------------- .../roomfinder/DungeonRoomInfoRegistry.java | 4 +- 3 files changed, 63 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/main/java/kr/syeyoung/dungeonsguide/Authenticator.java b/src/main/java/kr/syeyoung/dungeonsguide/Authenticator.java index 9fc16054..eb6cecb6 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/Authenticator.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/Authenticator.java @@ -8,18 +8,20 @@ import com.mojang.authlib.minecraft.MinecraftSessionService; import lombok.Getter; import net.minecraft.client.Minecraft; import net.minecraft.util.Session; +import org.apache.commons.io.IOUtils; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.math.BigInteger; import java.net.*; import java.security.*; +import java.util.HashMap; import java.util.UUID; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; public class Authenticator { @Getter @@ -44,7 +46,7 @@ public class Authenticator { private static final String DOMAIN = "http://localhost:8080/"; - public String authenticate() throws IOException, AuthenticationException, NoSuchAlgorithmException { + public String authenticate() throws IOException, AuthenticationException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException { Session session = Minecraft.getMinecraft().getSession(); String token = session.getToken(); @@ -55,6 +57,7 @@ public class Authenticator { DatatypeConverter.parseBase64Binary(jwt2.get("publicKey").getAsString())); yggdrasilMinecraftSessionService.joinServer(session.getProfile(), token, hash); this.token = requestAuth2(jwt, keyPair.getPublic()); + load(this.token); return this.token; } @@ -96,6 +99,53 @@ public class Authenticator { } return object.get("data").getAsString(); } + + @Getter + private HashMap dynamicResources = new HashMap(); + + private void load(String token) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException { + HttpURLConnection huc = (HttpURLConnection) new URL(DOMAIN + "resource/jar").openConnection(); + huc.setRequestProperty("User-Agent", "DungeonsGuide/1.0"); + huc.setRequestProperty("Content-Type", "application/json"); + huc.setRequestMethod("GET"); + huc.setRequestProperty("Authorization", token); + huc.setDoInput(true); + huc.setDoOutput(true); + System.out.println("Resp Code::" + huc.getResponseCode()); + + InputStream inputStream = huc.getInputStream(); + byte[] bytes = new byte[4]; + inputStream.read(bytes); + int len = ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF)); + while (inputStream.available() < len) ; + byte[] pubKey = new byte[len]; + inputStream.read(pubKey); + + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + byte[] byteEncrypted = pubKey; + cipher.init(Cipher.DECRYPT_MODE, getKeyPair().getPrivate()); + byte[] bytePlain = cipher.doFinal(byteEncrypted); + + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(bytePlain, "AES"); + IvParameterSpec ivSpec = new IvParameterSpec(bytePlain); + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); + CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher); + + cipherInputStream.read(bytes); + ZipInputStream inputStream1 = new ZipInputStream(cipherInputStream); + ZipEntry zipEntry; + while ((zipEntry=inputStream1.getNextEntry()) != null) { + byte[] content = new byte[(int) zipEntry.getSize()]; + IOUtils.readFully(inputStream1, content); + dynamicResources.put(zipEntry.getName(), content); + } + huc.disconnect(); + } + public String calculateAuthHash(byte[] sharedSecret, byte[] pk) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update("".getBytes()); diff --git a/src/main/java/kr/syeyoung/dungeonsguide/customurl/DGURLConnection.java b/src/main/java/kr/syeyoung/dungeonsguide/customurl/DGURLConnection.java index 1469a064..5f68ad97 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/customurl/DGURLConnection.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/customurl/DGURLConnection.java @@ -14,10 +14,11 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; -public class DGURLConnection extends HttpURLConnection { - private static final String DOMAIN = "http://localhost:8080/"; - +public class DGURLConnection extends URLConnection { private Authenticator authenticator; protected DGURLConnection(URL url, Authenticator authenticator) { super(url); @@ -25,102 +26,13 @@ public class DGURLConnection extends HttpURLConnection { this.authenticator = authenticator; } - private boolean exists= false; - @Override public void connect() throws IOException { - try { - if (!(url.getPath().contains("kr/syeyoung") || url.getPath().contains("roomdata"))) return; - this.connected = true; - - boolean classLoader = false; - for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { - if (ste.getClassName().equals("net.minecraft.launchwrapper.LaunchClassLoader")) { - classLoader = true; - } - } - - - System.out.println("loading " + url.getPath().substring(1) + " called from classloader " + classLoader); - - HttpURLConnection huc = (HttpURLConnection) new URL(DOMAIN + "resource/resource?class=" + URLEncoder.encode(url.getPath().substring(1))).openConnection(); - huc.setRequestProperty("User-Agent", "DungeonsGuide/1.0"); - huc.setRequestProperty("Content-Type", "application/json"); - huc.setRequestMethod(method.equals("HEAD") ? "HEAD" : "GET"); - huc.setRequestProperty("Authorization", (url.getUserInfo() == null && classLoader) ? authenticator.getToken() : url.getUserInfo()); - huc.setDoInput(true); - huc.setDoOutput(true); - System.out.println("Resp Code::" + huc.getResponseCode() + "/ " + method); - - exists = huc.getResponseCode() != 404; - if (method.equals("HEAD")) { - return; - } - - InputStream inputStream = huc.getInputStream(); - byte[] bytes = new byte[4]; - inputStream.read(bytes); - int len = ((bytes[0] & 0xFF) << 24) | - ((bytes[1] & 0xFF) << 16) | - ((bytes[2] & 0xFF) << 8) | - ((bytes[3] & 0xFF)); - while (inputStream.available() < len) ; - byte[] pubKey = new byte[len]; - inputStream.read(pubKey); - - Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); - byte[] byteEncrypted = pubKey; - cipher.init(Cipher.DECRYPT_MODE, authenticator.getKeyPair().getPrivate()); - byte[] bytePlain = cipher.doFinal(byteEncrypted); - - cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - SecretKeySpec keySpec = new SecretKeySpec(bytePlain, "AES"); - IvParameterSpec ivSpec = new IvParameterSpec(bytePlain); - cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); - CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher); - - cipherInputStream.read(bytes); - int length = ((bytes[0] & 0xFF) << 24) | - ((bytes[1] & 0xFF) << 16) | - ((bytes[2] & 0xFF) << 8) | - ((bytes[3] & 0xFF)); - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - int totalLen = 0; - try { - byte[] buffer = new byte[128]; - int read = 0; - while ((read = cipherInputStream.read(buffer)) != -1) { - totalLen += read; - byteStream.write(buffer, 0, read); - if (totalLen >= length) break; - } - } catch (Exception ignored) { - } - byte[] byte1 = byteStream.toByteArray(); - byte[] byte2 = new byte[(int) length]; - System.arraycopy(byte1, 0, byte2, 0, byte2.length); - cipherInputStream.close(); - inputStream.close(); - this.inputStream = new ByteArrayInputStream(byte2); - } catch (Throwable throwable) { - throwable.printStackTrace(); - } } - private InputStream inputStream; - @Override public InputStream getInputStream() throws IOException { - if (!connected) connect(); - if (method.equals("HEAD") && !exists) throw new FileNotFoundException(); - return inputStream; - } - - @Override - public void disconnect() { - } - - @Override - public boolean usingProxy() { - return false; + String path = url.getPath().substring(1); + if (!authenticator.getDynamicResources().containsKey(path)) throw new FileNotFoundException(); + return new ByteArrayInputStream(authenticator.getDynamicResources().get(path)); } } diff --git a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java index b08adbbe..03c2cb07 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java @@ -69,12 +69,12 @@ public class DungeonRoomInfoRegistry { registered.clear(); shapeMap.clear(); uuidMap.clear(); - URL url = new URL("dungeonsguide://"+DungeonsGuide.getDungeonsGuide().getAuthenticator().getToken()+"@/roomdata/datas.txt"); + URL url = new URL("dungeonsguide:///roomdata/datas.txt"); List lines = IOUtils.readLines(url.openConnection().getInputStream()); for (String name : lines) { if (!name.endsWith(".roomdata")) continue; try { - InputStream fis = new URL("dungeonsguide://"+DungeonsGuide.getDungeonsGuide().getAuthenticator().getToken()+"@/"+name).openStream(); + InputStream fis = new URL("dungeonsguide:///"+name).openStream(); ObjectInputStream ois = new ObjectInputStream(fis); DungeonRoomInfo dri = (DungeonRoomInfo) ois.readObject(); ois.close(); -- cgit