├── .gitattributes ├── .gitignore ├── README.md ├── pom.xml └── src └── main └── java └── me └── pringles └── lcwebsocketclient ├── Main.java ├── assets ├── AssetsPacket.java ├── ServerStatus.java ├── Websocket.java ├── packet │ ├── CPacketMods.java │ ├── SPacketAuthentication.java │ ├── SPacketBulkFriends.java │ ├── SPacketConnection.java │ ├── SPacketCosmetics.java │ ├── SPacketEmotes.java │ ├── SPacketFormattedConsoleOutput.java │ ├── SPacketFriendUpdate.java │ ├── ShPacketConsole.java │ ├── ShPacketFriendRemove.java │ ├── ShPacketFriendRequest.java │ ├── ShPacketFriendRequestUpdate.java │ ├── ShPacketFriendUpdate.java │ ├── ShPacketMessage.java │ └── ShPacketStatusUpdate.java └── user │ └── Status.java ├── auth ├── AuthWebsocket.java └── packet │ ├── AuthPacket.java │ ├── Packet.java │ └── auth │ ├── CPacketEncryptionResponse.java │ ├── SPacketAuthenticatedRequest.java │ └── SPacketEncryptionRequest.java └── util ├── AuthUtil.java ├── ByteBufWrapper.java ├── Config.java └── CryptManager.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | dependency-reduced-pom.xml 8 | buildNumber.properties 9 | .mvn/timing.properties 10 | .mvn/wrapper/maven-wrapper.jar 11 | *.properties 12 | # Eclipse stuff 13 | .classpath 14 | .project 15 | .settings/ 16 | 17 | # netbeans 18 | nbproject/ 19 | nbactions.xml 20 | 21 | # we use maven! 22 | build.xml 23 | 24 | # maven 25 | target/ 26 | dependency-reduced-pom.xml 27 | 28 | # vim 29 | .*.sw[a-p] 30 | 31 | # various other potential build files 32 | build/ 33 | bin/ 34 | dist/ 35 | manifest.mf 36 | 37 | # Mac filesystem dust 38 | .DS_Store/ 39 | .DS_Store 40 | 41 | # intellij 42 | *.iml 43 | *.ipr 44 | *.iws 45 | .idea/ 46 | 47 | working-dir/ 48 | config.properties -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LCWebsocket 2 | 3 | ### What dis? 4 | This is a console version of Lunar Client. It connects to their assets websocket, you can do basically everything with this. 5 | 6 | ### How to use? 7 | Rename the `config.properties.example` to `config.properties` then fill it in. Run it using IntellIJ. 8 | 9 | ### Update??? 10 | It works again!!! 11 | 12 | ### Why??? 13 | I made this so I could play around with the actual websocket, and try to find out how it actually works. 14 | 15 | ### Credits 16 | [Decencies](https://github.com/Decencies) for helping with with some of the packet names 17 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | me.pringles 8 | LunarWebsocketClient 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 8 13 | 8 14 | 15 | 16 | 17 | 18 | minecraft-repo 19 | https://libraries.minecraft.net/ 20 | 21 | 22 | 23 | 24 | 25 | com.google.guava 26 | guava 27 | 30.1.1-jre 28 | 29 | 30 | org.java-websocket 31 | Java-WebSocket 32 | 1.5.2 33 | 34 | 35 | com.google.code.gson 36 | gson 37 | 2.8.6 38 | 39 | 40 | com.mojang 41 | authlib 42 | 1.5.21 43 | compile 44 | 45 | 46 | io.netty 47 | netty-all 48 | 4.1.63.Final 49 | 50 | 51 | org.projectlombok 52 | lombok 53 | 1.16.18 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/Main.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import com.google.gson.Gson; 5 | import com.google.gson.GsonBuilder; 6 | import lombok.Getter; 7 | import me.pringles.lcwebsocketclient.assets.Websocket; 8 | import me.pringles.lcwebsocketclient.assets.packet.ShPacketConsole; 9 | import me.pringles.lcwebsocketclient.assets.packet.ShPacketFriendRequest; 10 | import me.pringles.lcwebsocketclient.assets.packet.ShPacketMessage; 11 | import me.pringles.lcwebsocketclient.auth.AuthWebsocket; 12 | import me.pringles.lcwebsocketclient.util.Config; 13 | 14 | import java.io.BufferedReader; 15 | import java.io.IOException; 16 | import java.io.InputStreamReader; 17 | import java.net.URISyntaxException; 18 | import java.util.function.Consumer; 19 | 20 | public class Main { 21 | public static Gson gson = new GsonBuilder().create(); 22 | @Getter private static Config config; 23 | 24 | public static void main(String[] args) throws IOException { 25 | config = new Config(); 26 | new Thread(() -> connectToAuth(s -> { 27 | try { 28 | System.out.println("Got auth key, connecting to assets websocket"); 29 | Websocket websocket = new Websocket(ImmutableMap.builder().put("accountType", "MOJANG").put("version", "v1_8").put("gitCommit", "2ef0680874b1d11cea10a4b969c6f5ec1f804d70").put("branch", "master").put("os", System.getProperty("os.name")).put("arch", "").put("server", "pornhub.com").put("launcherVersion", "2.4.1").put("username", config.getUsername()).put("playerId", config.getUuid()).put("Authorization", s).put("clothCloak", "false").put("hwid", "myHWID").build()); 30 | websocket.connect(); 31 | } catch (URISyntaxException e) { 32 | e.printStackTrace(); 33 | } 34 | })).start(); 35 | while (true) { 36 | BufferedReader reader = new BufferedReader( 37 | new InputStreamReader(System.in)); 38 | 39 | String message = reader.readLine(); 40 | Websocket.getInstance().sendPacket(new ShPacketMessage(Websocket.getLastMessage(), message)); 41 | } 42 | } 43 | 44 | public static void connectToAuth(Consumer consumer) { 45 | try { 46 | new AuthWebsocket(ImmutableMap.builder().put("username", config.getUsername()).put("playerId", config.getUuid()).build(), consumer).connect(); 47 | } catch (URISyntaxException e) { 48 | e.printStackTrace(); 49 | consumer.accept(null); 50 | } 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/AssetsPacket.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets; 2 | 3 | 4 | import com.google.common.collect.BiMap; 5 | import com.google.common.collect.HashBiMap; 6 | import io.netty.buffer.ByteBuf; 7 | import me.pringles.lcwebsocketclient.assets.packet.*; 8 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 9 | 10 | import java.io.IOException; 11 | 12 | public abstract class AssetsPacket { 13 | 14 | public static BiMap, Integer> REGISTRY = HashBiMap.create(); 15 | 16 | public abstract void write(ByteBufWrapper var1); 17 | 18 | public abstract void read(ByteBufWrapper var1) throws IOException; 19 | 20 | public abstract void handle(Websocket var1); 21 | 22 | protected void writeKey(ByteBuf byteBuf, byte[] key) { 23 | byteBuf.writeShort(key.length); 24 | byteBuf.writeBytes(key); 25 | } 26 | 27 | protected byte[] readKey(ByteBuf byteBuf) { 28 | short keySize = byteBuf.readShort(); 29 | if (keySize >= 0) { 30 | byte[] key = new byte[keySize]; 31 | byteBuf.readBytes(key); 32 | return key; 33 | } 34 | return new byte[0]; 35 | } 36 | 37 | static { 38 | REGISTRY.put(SPacketAuthentication.class, 1); 39 | REGISTRY.put(ShPacketConsole.class, 2); 40 | REGISTRY.put(SPacketFormattedConsoleOutput.class, 3); 41 | REGISTRY.put(SPacketConnection.class, 4); 42 | REGISTRY.put(ShPacketMessage.class, 5); 43 | REGISTRY.put(ShPacketStatusUpdate.class, 6); 44 | REGISTRY.put(SPacketBulkFriends.class, 7); 45 | REGISTRY.put(SPacketCosmetics.class, 8); 46 | REGISTRY.put(ShPacketFriendRequest.class, 9); 47 | REGISTRY.put(SPacketFriendUpdate.class, 16); 48 | REGISTRY.put(ShPacketFriendRemove.class, 17); 49 | REGISTRY.put(ShPacketFriendUpdate.class, 18); 50 | REGISTRY.put(ShPacketFriendRequestUpdate.class, 21); 51 | REGISTRY.put(SPacketEmotes.class, 57); 52 | REGISTRY.put(CPacketMods.class, 64); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return this.getClass().getSimpleName(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/ServerStatus.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets; 2 | 3 | public enum ServerStatus { 4 | DISCONNECTED, 5 | AWAITING_ENCRYPTION_REQUEST, 6 | AUTHENTICATING, 7 | READY 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/Websocket.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets; 2 | 3 | import io.netty.buffer.Unpooled; 4 | import lombok.Getter; 5 | import me.pringles.lcwebsocketclient.assets.packet.*; 6 | import me.pringles.lcwebsocketclient.assets.user.Status; 7 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 8 | import org.java_websocket.client.WebSocketClient; 9 | import org.java_websocket.drafts.Draft_6455; 10 | import org.java_websocket.handshake.ServerHandshake; 11 | 12 | import java.net.URI; 13 | import java.net.URISyntaxException; 14 | import java.nio.ByteBuffer; 15 | import java.util.Date; 16 | import java.util.Map; 17 | import java.util.regex.Matcher; 18 | import java.util.regex.Pattern; 19 | 20 | public class Websocket extends WebSocketClient { 21 | 22 | private ServerStatus status = ServerStatus.DISCONNECTED; 23 | private String server; 24 | @Getter 25 | public static String lastMessage; 26 | 27 | @Getter 28 | public static Websocket instance; 29 | 30 | public Websocket(final Map map) throws URISyntaxException { 31 | super(new URI("wss://assetserver.lunarclientprod.com/connect"), new Draft_6455(), map, 0); 32 | server = null; 33 | instance = this; 34 | } 35 | 36 | @Override 37 | public void onOpen(ServerHandshake serverHandshake) { 38 | this.status = ServerStatus.AWAITING_ENCRYPTION_REQUEST; 39 | } 40 | 41 | @Override 42 | public void onMessage(String s) { 43 | } 44 | 45 | @Override 46 | public void onMessage(ByteBuffer bytes) { 47 | this.handleIncoming(new ByteBufWrapper(Unpooled.wrappedBuffer(bytes.array()))); 48 | 49 | } 50 | 51 | public void handleIncoming(ByteBufWrapper buf) { 52 | int n = buf.readVarInt(); 53 | Class packetClass = AssetsPacket.REGISTRY.inverse().get(n); 54 | try { 55 | AssetsPacket packet = packetClass == null ? null : packetClass.newInstance(); 56 | if (packet == null) { 57 | System.out.println("Got unknown packet: " + n); 58 | return; 59 | } 60 | System.out.println("Got packet: " + packet); 61 | packet.read(buf); 62 | packet.handle(this); 63 | } catch (Exception exception) { 64 | System.out.println("Error from: " + packetClass); 65 | exception.printStackTrace(); 66 | } 67 | } 68 | 69 | @Override 70 | public void onClose(int i, String s, boolean b) { 71 | System.out.println(i + s); 72 | this.status = ServerStatus.DISCONNECTED; 73 | } 74 | 75 | public void handleAuthentication(SPacketAuthentication packetAuthentication) { 76 | this.status = ServerStatus.AUTHENTICATING; 77 | } 78 | 79 | public void sendConsoleMessage(String command){ 80 | sendPacket(new ShPacketConsole(command)); 81 | System.out.println("Sending " + command + " to lunar console"); 82 | } 83 | 84 | @Override 85 | public void onError(Exception e) { 86 | e.printStackTrace(); 87 | } 88 | 89 | public void sendPacket(AssetsPacket packet) { 90 | if (!this.isOpen()) { 91 | return; 92 | } 93 | ByteBufWrapper buf = new ByteBufWrapper(Unpooled.buffer()); 94 | buf.writeVarInt(AssetsPacket.REGISTRY.get(packet.getClass())); 95 | try { 96 | packet.write(buf); 97 | byte[] bytes = new byte[buf.buf().readableBytes()]; 98 | buf.buf().readBytes(bytes); 99 | buf.buf().release(); 100 | this.send(bytes); 101 | } catch (Exception e) { 102 | e.printStackTrace(); 103 | } 104 | } 105 | 106 | private void setServer(String server) { 107 | final Matcher ipRegex = Pattern.compile("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)").matcher(server); 108 | ; 109 | this.server = server; 110 | if (!ipRegex.find()) { 111 | //Ip not numeric.. Sending it. 112 | this.sendPacket(new ShPacketStatusUpdate("", server)); 113 | } else { 114 | this.sendPacket(new ShPacketStatusUpdate("", "_numeric_")); 115 | } 116 | } 117 | 118 | public void handleConnection(SPacketConnection packetConnection) { 119 | this.status = ServerStatus.READY; 120 | setServer("hypixel.net"); 121 | 122 | new Thread(() -> { 123 | while (true) { 124 | sendPacket(new CPacketMods()); 125 | try { 126 | Thread.sleep(60); 127 | } catch (InterruptedException e) { 128 | e.printStackTrace(); 129 | } 130 | } 131 | }).start(); 132 | 133 | } 134 | 135 | public void handleServerChange(ShPacketStatusUpdate packetServerUpdate) { 136 | System.out.println("Server changed for user: " + packetServerUpdate.getPlayerId() + " to: " + packetServerUpdate.getServer()); 137 | } 138 | 139 | public void handleFriendRequest(ShPacketFriendRequest packetFriendRequest) { 140 | System.out.println("Got friend request from: " + packetFriendRequest.getName() + ", accepting it."); 141 | this.sendPacket(new ShPacketFriendRequestUpdate(true, packetFriendRequest.getPlayerId())); 142 | } 143 | 144 | public void handleMessage(ShPacketMessage packetMessage) { 145 | System.out.println("Got message: " + packetMessage.getMessage() + " From: " + packetMessage.getPlayerId() + " Setting user as console target."); 146 | lastMessage = packetMessage.getPlayerId(); 147 | 148 | if(packetMessage.getMessage().startsWith("!")){ 149 | String[] args = packetMessage.getMessage().substring("!".length()).split(" "); 150 | if(args[0].equals("setserver")){ 151 | setServer(args[1]); 152 | sendPacket(new ShPacketMessage(packetMessage.getPlayerId(), "Set server to " + args[1])); 153 | } 154 | 155 | } 156 | } 157 | 158 | public void handleConsole(SPacketFormattedConsoleOutput packetFormattedConsoleOutput) { 159 | System.out.println("[" + packetFormattedConsoleOutput.getPrefix() + "] " + packetFormattedConsoleOutput.getContent()); 160 | } 161 | 162 | public void handleRawConsole(ShPacketConsole packetConsole) { 163 | System.out.println(packetConsole.getOutput()); 164 | } 165 | 166 | public void handleFriendUpdate(ShPacketFriendUpdate packetFriendUpdate) { 167 | if(packetFriendUpdate.getStatus() < 10L){ 168 | Status status = Status.ONLINE; 169 | for(Status status1 : Status.values()){ 170 | if(status1.ordinal() == packetFriendUpdate.getStatus()){ 171 | status = status1; 172 | } 173 | } 174 | System.out.println(packetFriendUpdate.getName() + " went on status " + status.getName()); 175 | return; 176 | } 177 | System.out.println(packetFriendUpdate.getName() + " went offline! they were last seen at: " + new Date(packetFriendUpdate.getStatus())); 178 | } 179 | 180 | public void handleFriendRemove(ShPacketFriendRemove packetClientFriendRemove){ 181 | System.out.println(packetClientFriendRemove.getPlayerId() + " Removed us as friend! Sending new friend request."); 182 | this.sendPacket(new ShPacketFriendRequest(packetClientFriendRemove.getPlayerId(), "")); 183 | } 184 | 185 | public void handleFriendUpdate(SPacketFriendUpdate packetFriendUpdate){ 186 | System.out.println("Got friend update, " + packetFriendUpdate.toString()); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/CPacketMods.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 5 | import me.pringles.lcwebsocketclient.assets.Websocket; 6 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class CPacketMods extends AssetsPacket { 12 | 13 | private final String string; 14 | private final Map map ; 15 | 16 | 17 | public CPacketMods(){ 18 | map = new HashMap<>(); 19 | this.string = ""; 20 | this.map.put("skyblockaddons", false); 21 | } 22 | @Override 23 | public void write(ByteBufWrapper wrapper) { 24 | wrapper.writeVarInt(map.size()); 25 | this.map.forEach((s, aBoolean) -> { 26 | wrapper.writeString(s); 27 | wrapper.buf().writeBoolean(aBoolean); 28 | }); 29 | wrapper.writeString(string); 30 | } 31 | 32 | @Override 33 | public void read(ByteBufWrapper wrapper) { 34 | } 35 | 36 | @Override 37 | public void handle(Websocket websocket) { 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/SPacketAuthentication.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 5 | import me.pringles.lcwebsocketclient.assets.Websocket; 6 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 7 | 8 | public class SPacketAuthentication extends AssetsPacket { 9 | 10 | @Override 11 | public void write(ByteBufWrapper wrapper) { 12 | } 13 | 14 | @Override 15 | public void read(ByteBufWrapper wrapper) { 16 | } 17 | 18 | @Override 19 | public void handle(Websocket websocket) { 20 | websocket.handleAuthentication(this); 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/SPacketBulkFriends.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.JsonParser; 7 | import lombok.Getter; 8 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 9 | import me.pringles.lcwebsocketclient.assets.Websocket; 10 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 11 | 12 | import java.io.IOException; 13 | 14 | @Getter 15 | public class SPacketBulkFriends extends AssetsPacket { 16 | 17 | private String rawRequests; 18 | private JsonArray friends; 19 | 20 | @Override 21 | public void write(ByteBufWrapper wrapper) { 22 | } 23 | 24 | @Override 25 | public void read(ByteBufWrapper wrapper) throws IOException { 26 | this.rawRequests = wrapper.readString(); 27 | JsonObject jsonObject = new JsonParser().parse(this.rawRequests).getAsJsonObject(); 28 | System.out.println(jsonObject); 29 | this.friends = jsonObject.getAsJsonArray("bulk"); 30 | } 31 | 32 | @Override 33 | public void handle(Websocket websocket) { 34 | //websocket.handleAuthentication(this); 35 | } 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/SPacketConnection.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import lombok.*; 5 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 6 | import me.pringles.lcwebsocketclient.assets.Websocket; 7 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 8 | 9 | import java.io.IOException; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | @Getter 14 | @ToString 15 | public class SPacketConnection extends AssetsPacket { 16 | 17 | private boolean consoleAllowed; 18 | public boolean friendRequestsEnabled; 19 | public Map> onlineFriends; 20 | public Map> offlineFriends; 21 | 22 | @Override 23 | public void write(ByteBufWrapper var1) { 24 | 25 | } 26 | 27 | @Override 28 | public void read(ByteBufWrapper var1) throws IOException { 29 | int n; 30 | this.consoleAllowed = var1.buf().readBoolean(); 31 | this.friendRequestsEnabled = var1.buf().readBoolean(); 32 | int n2 = var1.buf().readInt(); 33 | int n3 = var1.buf().readInt();; 34 | this.onlineFriends = new HashMap<>(); 35 | for (n = 0; n < n2; ++n) { 36 | this.onlineFriends.put(var1.readStringFromBuffer(52), ImmutableList.of(var1.readStringFromBuffer(32), String.valueOf(var1.buf().readInt()), var1.readStringFromBuffer(256))); 37 | } 38 | this.offlineFriends = new HashMap<>(); 39 | for (n = 0; n < n3; ++n) { 40 | this.offlineFriends.put(var1.readStringFromBuffer(52), ImmutableList.of(var1.readStringFromBuffer(32), String.valueOf(var1.buf().readLong()))); 41 | } 42 | System.out.println(this); 43 | } 44 | 45 | @Override 46 | public void handle(Websocket var1) { 47 | var1.handleConnection(this); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/SPacketCosmetics.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 4 | 5 | import me.pringles.lcwebsocketclient.assets.Websocket; 6 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.UUID; 11 | 12 | public class SPacketCosmetics extends AssetsPacket { 13 | private UUID target; 14 | private List cosmetics; 15 | private int color = -1; 16 | private boolean thing; 17 | private boolean thing2; 18 | private boolean thing3; 19 | 20 | @Override 21 | public void write(ByteBufWrapper var1) { 22 | 23 | } 24 | 25 | @Override 26 | public void read(ByteBufWrapper var1) { 27 | target = new UUID(var1.buf().readLong(), var1.buf().readLong()); 28 | int n = var1.readVarInt(); 29 | cosmetics = new ArrayList(n); 30 | for (int i = 0; i < n; ++i) { 31 | int n2 = var1.readVarInt(); 32 | boolean bl = var1.buf().readBoolean(); 33 | System.out.println("Got cosmetic with id: " + n2 + " enabled: " + bl); 34 | try { 35 | this.cosmetics.add(n2); 36 | continue; 37 | } 38 | catch (Exception exception) { 39 | exception.printStackTrace(); 40 | } 41 | } 42 | this.color = var1.buf().readInt(); 43 | this.thing = var1.buf().readBoolean(); 44 | this.thing2 = var1.buf().readBoolean(); 45 | //this.thing3 = var1.buf().readBoolean(); 46 | } 47 | 48 | @Override 49 | public void handle(Websocket var1) { 50 | 51 | } 52 | 53 | 54 | @Override 55 | public String toString() { 56 | return "SPacketCosmetics{" + 57 | "target=" + target + 58 | ", cosmetics=" + cosmetics + 59 | ", color=" + color + 60 | ", thing=" + thing + 61 | ", thing2=" + thing2 + 62 | ", thing3=" + thing3 + 63 | '}'; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/SPacketEmotes.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 5 | import me.pringles.lcwebsocketclient.assets.Websocket; 6 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class SPacketEmotes extends AssetsPacket { 12 | private List list1; 13 | private List list2; 14 | 15 | @Override 16 | public void write(ByteBufWrapper wrapper) { 17 | } 18 | 19 | @Override 20 | public void read(ByteBufWrapper wrapper) { 21 | int n; 22 | int n2 = wrapper.readVarInt(); 23 | this.list1 = new ArrayList(); 24 | for (n = 0; n < n2; ++n) { 25 | this.list1.add(wrapper.readVarInt()); 26 | } 27 | this.list2 = new ArrayList<>(); 28 | for (n = 0; n < n2; ++n) { 29 | this.list2.add(wrapper.readVarInt()); 30 | } 31 | } 32 | 33 | @Override 34 | public void handle(Websocket websocket) { 35 | 36 | } 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/SPacketFormattedConsoleOutput.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.NoArgsConstructor; 6 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 7 | import me.pringles.lcwebsocketclient.assets.Websocket; 8 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 9 | 10 | import java.io.IOException; 11 | 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class SPacketFormattedConsoleOutput 15 | extends AssetsPacket { 16 | private String prefix; 17 | private String content; 18 | 19 | @Override 20 | public void write(ByteBufWrapper buf) { 21 | buf.writeString(this.prefix); 22 | buf.writeString(this.content); 23 | } 24 | 25 | @Override 26 | public void read(ByteBufWrapper buf) throws IOException { 27 | this.prefix = buf.readStringFromBuffer(128); 28 | this.content = buf.readStringFromBuffer(512); 29 | } 30 | 31 | @Override 32 | public void handle(Websocket websocket) { 33 | websocket.handleConsole(this); 34 | } 35 | 36 | public String getPrefix() { 37 | return this.prefix; 38 | } 39 | 40 | public String getContent() { 41 | return this.content; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/SPacketFriendUpdate.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.ToString; 8 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 9 | import me.pringles.lcwebsocketclient.assets.Websocket; 10 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 11 | 12 | import java.io.IOException; 13 | 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @Getter 17 | @ToString 18 | public class SPacketFriendUpdate extends AssetsPacket { 19 | private String playerId; 20 | private String name; 21 | private boolean friend; 22 | 23 | @Override 24 | public void write(ByteBufWrapper wrapper) { 25 | wrapper.writeString(this.playerId); 26 | wrapper.writeString(this.name); 27 | wrapper.buf().writeBoolean(this.friend); 28 | } 29 | 30 | @Override 31 | public void read(ByteBufWrapper wrapper) throws IOException { 32 | this.playerId = wrapper.readStringFromBuffer(52); 33 | this.name = wrapper.readStringFromBuffer(32); 34 | this.friend = wrapper.buf().readBoolean(); 35 | } 36 | 37 | @Override 38 | public void handle(Websocket websocket) { 39 | websocket.handleFriendUpdate(this); 40 | } 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/ShPacketConsole.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 7 | import me.pringles.lcwebsocketclient.assets.Websocket; 8 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 9 | 10 | import java.io.IOException; 11 | 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ShPacketConsole extends AssetsPacket { 15 | @Getter 16 | private String output; 17 | 18 | @Override 19 | public void write(ByteBufWrapper buf) { 20 | buf.writeString(this.output); 21 | } 22 | 23 | @Override 24 | public void read(ByteBufWrapper buf) throws IOException { 25 | this.output = buf.readStringFromBuffer(32767); 26 | } 27 | 28 | @Override 29 | public void handle(Websocket websocket) { 30 | websocket.handleRawConsole(this); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/ShPacketFriendRemove.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 8 | import me.pringles.lcwebsocketclient.assets.Websocket; 9 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 10 | 11 | import java.io.IOException; 12 | 13 | @Getter 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class ShPacketFriendRemove extends AssetsPacket { 17 | private String playerId; 18 | 19 | @Override 20 | public void write(ByteBufWrapper buf) { 21 | buf.writeString(this.playerId); 22 | } 23 | 24 | @Override 25 | public void read(ByteBufWrapper buf) throws IOException { 26 | this.playerId = buf.readStringFromBuffer(52); 27 | } 28 | 29 | @Override 30 | public void handle(Websocket websocket) { 31 | websocket.handleFriendRemove(this); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/ShPacketFriendRequest.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 5 | import me.pringles.lcwebsocketclient.assets.Websocket; 6 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 7 | 8 | import java.io.IOException; 9 | 10 | public class ShPacketFriendRequest 11 | extends AssetsPacket { 12 | private String playerId; 13 | private String name; 14 | 15 | public ShPacketFriendRequest() { 16 | } 17 | 18 | public ShPacketFriendRequest(String playerId, String name) { 19 | this.playerId = playerId; 20 | this.name = name; 21 | } 22 | 23 | @Override 24 | public void write(ByteBufWrapper buf) { 25 | buf.writeString(this.playerId); 26 | buf.writeString(this.name); 27 | } 28 | 29 | @Override 30 | public void read(ByteBufWrapper buf) throws IOException { 31 | this.playerId = buf.readStringFromBuffer(52); 32 | this.name = buf.readStringFromBuffer(32); 33 | } 34 | 35 | @Override 36 | public void handle(Websocket websocket) { 37 | websocket.handleFriendRequest(this); 38 | } 39 | 40 | public String getPlayerId() { 41 | return this.playerId; 42 | } 43 | 44 | public String getName() { 45 | return this.name; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/ShPacketFriendRequestUpdate.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.NoArgsConstructor; 6 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 7 | import me.pringles.lcwebsocketclient.assets.Websocket; 8 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 9 | 10 | import java.io.IOException; 11 | 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class ShPacketFriendRequestUpdate 15 | extends AssetsPacket { 16 | private boolean add; 17 | private String playerId; 18 | 19 | 20 | @Override 21 | public void write(ByteBufWrapper buf) { 22 | buf.buf().writeBoolean(this.add); 23 | buf.writeString(this.playerId); 24 | } 25 | 26 | @Override 27 | public void read(ByteBufWrapper buf) throws IOException { 28 | this.add = buf.buf().readBoolean(); 29 | this.playerId = buf.readStringFromBuffer(52); 30 | } 31 | 32 | @Override 33 | public void handle(Websocket websocket) { 34 | } 35 | 36 | public boolean isAdd() { 37 | return this.add; 38 | } 39 | 40 | public String lIIIIIIIIIlIllIIllIlIIlIl() { 41 | return this.playerId; 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/ShPacketFriendUpdate.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 7 | import me.pringles.lcwebsocketclient.assets.Websocket; 8 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 9 | 10 | import java.io.IOException; 11 | 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @Getter 15 | public class ShPacketFriendUpdate extends AssetsPacket { 16 | private String playerId; 17 | private String name; 18 | private long status; 19 | private boolean online; 20 | 21 | @Override 22 | public void write(ByteBufWrapper buf) { 23 | buf.writeString(this.playerId); 24 | buf.writeString(this.name); 25 | buf.buf().writeLong(status); 26 | buf.buf().writeBoolean(online); 27 | } 28 | 29 | @Override 30 | public void read(ByteBufWrapper buf) throws IOException { 31 | this.playerId = buf.readStringFromBuffer(52); 32 | this.name = buf.readStringFromBuffer(32); 33 | this.status = buf.buf().readLong(); 34 | this.online = buf.buf().readBoolean(); 35 | } 36 | 37 | @Override 38 | public void handle(Websocket var1) { 39 | var1.handleFriendUpdate(this); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/ShPacketMessage.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.NoArgsConstructor; 6 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 7 | import me.pringles.lcwebsocketclient.assets.Websocket; 8 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 9 | 10 | import java.io.IOException; 11 | 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ShPacketMessage 15 | extends AssetsPacket { 16 | private String playerId; 17 | private String message; 18 | 19 | @Override 20 | public void write(ByteBufWrapper buf) { 21 | buf.writeString(this.playerId); 22 | buf.writeString(this.message); 23 | } 24 | 25 | @Override 26 | public void read(ByteBufWrapper buf) throws IOException { 27 | this.playerId = buf.readStringFromBuffer(52); 28 | this.message = buf.readStringFromBuffer(1024); 29 | } 30 | 31 | @Override 32 | public void handle(Websocket websocket) { 33 | websocket.handleMessage(this); 34 | } 35 | 36 | public String getPlayerId() { 37 | return this.playerId; 38 | } 39 | 40 | public String getMessage() { 41 | return this.message; 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/packet/ShPacketStatusUpdate.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.packet; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.NoArgsConstructor; 6 | import me.pringles.lcwebsocketclient.assets.AssetsPacket; 7 | import me.pringles.lcwebsocketclient.assets.Websocket; 8 | import me.pringles.lcwebsocketclient.util.ByteBufWrapper; 9 | 10 | import java.io.IOException; 11 | 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ShPacketStatusUpdate extends AssetsPacket { 15 | private String playerId; 16 | private String server; 17 | 18 | 19 | @Override 20 | public void write(ByteBufWrapper buf) { 21 | buf.writeString(this.playerId); 22 | buf.writeString(this.server); 23 | } 24 | 25 | @Override 26 | public void read(ByteBufWrapper buf) throws IOException { 27 | this.playerId = buf.readStringFromBuffer(52); 28 | this.server = buf.readStringFromBuffer(100); 29 | } 30 | 31 | public void handle(Websocket websocket) { 32 | websocket.handleServerChange(this); 33 | } 34 | 35 | public String getServer() { 36 | return this.server; 37 | } 38 | 39 | public String getPlayerId() { 40 | return this.playerId; 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/assets/user/Status.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.assets.user; 2 | 3 | public enum Status { 4 | ONLINE( "Online"), 5 | AWAY("Away"), 6 | BUSY("Busy"), 7 | OFFLINE( "Offline"); 8 | 9 | public final String name; 10 | 11 | Status(final String name) { 12 | this.name = name; 13 | } 14 | 15 | public String getName() { 16 | return this.name; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/auth/AuthWebsocket.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.auth; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.JsonParser; 5 | import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; 6 | import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; 7 | import me.pringles.lcwebsocketclient.Main; 8 | import me.pringles.lcwebsocketclient.auth.packet.AuthPacket; 9 | import me.pringles.lcwebsocketclient.auth.packet.auth.CPacketEncryptionResponse; 10 | import me.pringles.lcwebsocketclient.auth.packet.auth.SPacketAuthenticatedRequest; 11 | import me.pringles.lcwebsocketclient.auth.packet.auth.SPacketEncryptionRequest; 12 | import me.pringles.lcwebsocketclient.util.AuthUtil; 13 | import me.pringles.lcwebsocketclient.util.CryptManager; 14 | import org.java_websocket.client.WebSocketClient; 15 | import org.java_websocket.drafts.Draft_6455; 16 | import org.java_websocket.handshake.ServerHandshake; 17 | 18 | import javax.crypto.SecretKey; 19 | import java.math.BigInteger; 20 | import java.net.Proxy; 21 | import java.net.URI; 22 | import java.net.URISyntaxException; 23 | import java.nio.ByteBuffer; 24 | import java.nio.charset.StandardCharsets; 25 | import java.security.PublicKey; 26 | import java.util.Map; 27 | import java.util.UUID; 28 | import java.util.function.Consumer; 29 | 30 | public class AuthWebsocket extends WebSocketClient { 31 | 32 | public final Consumer consumer; 33 | 34 | public AuthWebsocket(final Map map, Consumer consumer) throws URISyntaxException { 35 | super(new URI("wss://authenticator.lunarclientprod.com"), new Draft_6455(), map, 3000); 36 | this.consumer = consumer; 37 | System.out.println("Connecting to authenticator websocket for authentication key."); 38 | } 39 | 40 | @Override 41 | public void onOpen(ServerHandshake serverHandshake) { 42 | 43 | } 44 | 45 | @Override 46 | public void onMessage(String s) { 47 | System.out.println(s); 48 | } 49 | 50 | @Override 51 | public void onMessage(ByteBuffer bytes) { 52 | JsonObject jsonObject = new JsonParser().parse(new String(bytes.array())).getAsJsonObject(); 53 | System.out.println(jsonObject.toString()); 54 | handleJson(jsonObject); 55 | } 56 | 57 | public void handleJson(JsonObject jsonObject) { 58 | AuthPacket authPacket; 59 | switch (jsonObject.get("packetType").getAsString()) { 60 | case "SPacketEncryptionRequest": { 61 | authPacket = new SPacketEncryptionRequest(); 62 | break; 63 | } 64 | case "SPacketAuthenticatedRequest":{ 65 | authPacket = new SPacketAuthenticatedRequest(); 66 | break; 67 | } 68 | default: 69 | return; 70 | } 71 | authPacket.handle2(jsonObject); 72 | authPacket.handle(this); 73 | } 74 | 75 | public void handleEncryptionRequest(SPacketEncryptionRequest packetEncryptionRequest) { 76 | PublicKey publicKey = packetEncryptionRequest.publicKey; 77 | SecretKey secretKey = CryptManager.createNewSharedKey(); 78 | byte[] byArray = CryptManager.getServerIdHash("", publicKey, secretKey); 79 | if (byArray == null) { 80 | return; 81 | } 82 | 83 | String serverId = new BigInteger(byArray).toString(16); 84 | System.out.println("Server ID: " + serverId); 85 | YggdrasilUserAuthentication auth = AuthUtil.getAuth(Main.getConfig().getEmail(), Main.getConfig().getPassword()); 86 | try{ 87 | new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString()).createMinecraftSessionService().joinServer(auth.getSelectedProfile() ,auth.getAuthenticatedToken(), serverId); 88 | }catch (Exception e){ 89 | e.printStackTrace(); 90 | } 91 | this.sendPacket(new CPacketEncryptionResponse(secretKey, publicKey, packetEncryptionRequest.randomBytes)); 92 | } 93 | 94 | public void handleAuthenticated(SPacketAuthenticatedRequest packetAuthenticatedRequest){ 95 | this.close(); 96 | this.consumer.accept(packetAuthenticatedRequest.jwtKey); 97 | } 98 | public void sendPacket(AuthPacket authPacket) { 99 | if(!this.isOpen()){ 100 | return; 101 | } 102 | JsonObject jsonObject = new JsonObject(); 103 | jsonObject.addProperty("packetType", authPacket.getName()); 104 | try{ 105 | authPacket.handle1(jsonObject); 106 | this.send(Main.gson.toJson(jsonObject).getBytes(StandardCharsets.UTF_8)); 107 | System.out.println("Sent packet " + jsonObject); 108 | }catch (Exception e){ 109 | e.printStackTrace(); 110 | } 111 | } 112 | 113 | 114 | @Override 115 | public void onClose(int i, String s, boolean b) { 116 | } 117 | 118 | @Override 119 | public void onError(Exception e) { 120 | e.printStackTrace(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/auth/packet/AuthPacket.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.auth.packet; 2 | 3 | import me.pringles.lcwebsocketclient.auth.AuthWebsocket; 4 | 5 | public abstract class AuthPacket extends Packet{ 6 | 7 | public abstract void handle(AuthWebsocket websocket); 8 | 9 | public abstract String getName(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/auth/packet/Packet.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.auth.packet; 2 | 3 | public abstract class Packet { 4 | 5 | public abstract void handle1(Object var1); 6 | 7 | public abstract void handle2(Object var1); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/auth/packet/auth/CPacketEncryptionResponse.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.auth.packet.auth; 2 | 3 | import com.google.gson.JsonObject; 4 | import me.pringles.lcwebsocketclient.auth.AuthWebsocket; 5 | import me.pringles.lcwebsocketclient.auth.packet.AuthPacket; 6 | import me.pringles.lcwebsocketclient.util.CryptManager; 7 | 8 | import javax.crypto.SecretKey; 9 | import java.security.PublicKey; 10 | import java.util.Base64; 11 | 12 | public class CPacketEncryptionResponse extends AuthPacket { 13 | 14 | public final byte[] secretKey; 15 | public final byte[] publicKey; 16 | 17 | public CPacketEncryptionResponse(SecretKey secretKey, PublicKey publicKey, byte[] bytes) { 18 | this.secretKey = CryptManager.encryptData(publicKey, secretKey.getEncoded()); 19 | this.publicKey = CryptManager.encryptData(publicKey, bytes); 20 | } 21 | 22 | @Override 23 | public void handle(AuthWebsocket websocket) { 24 | 25 | } 26 | 27 | @Override 28 | public String getName() { 29 | return "CPacketEncryptionResponse"; 30 | } 31 | 32 | @Override 33 | public void handle1(Object var1) { 34 | this.parseJson((JsonObject) var1); 35 | 36 | } 37 | 38 | public void parseJson(JsonObject jsonObject){ 39 | Base64.Encoder encoder = Base64.getUrlEncoder(); 40 | jsonObject.addProperty("secretKey", new String(encoder.encode(this.secretKey))); 41 | jsonObject.addProperty("publicKey", new String(encoder.encode(this.publicKey))); 42 | } 43 | 44 | @Override 45 | public void handle2(Object var1) { 46 | this.parseJson((JsonObject) var1); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/auth/packet/auth/SPacketAuthenticatedRequest.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.auth.packet.auth; 2 | 3 | import com.google.gson.JsonObject; 4 | import me.pringles.lcwebsocketclient.auth.AuthWebsocket; 5 | import me.pringles.lcwebsocketclient.auth.packet.AuthPacket; 6 | 7 | public class SPacketAuthenticatedRequest extends AuthPacket { 8 | 9 | public String jwtKey; 10 | 11 | @Override 12 | public void handle(AuthWebsocket websocket) { 13 | websocket.handleAuthenticated(this); 14 | } 15 | 16 | @Override 17 | public String getName() { 18 | return "SPacketAuthenticatedRequest"; 19 | } 20 | 21 | public void handleJson(JsonObject jsonObject){ 22 | this.jwtKey = jsonObject.get("jwtKey").getAsString(); 23 | } 24 | 25 | @Override 26 | public void handle1(Object var1) { 27 | this.handleJson((JsonObject) var1); 28 | } 29 | 30 | @Override 31 | public void handle2(Object var1) { 32 | this.handleJson((JsonObject) var1); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/auth/packet/auth/SPacketEncryptionRequest.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.auth.packet.auth; 2 | 3 | import com.google.gson.JsonObject; 4 | import me.pringles.lcwebsocketclient.auth.AuthWebsocket; 5 | import me.pringles.lcwebsocketclient.auth.packet.AuthPacket; 6 | 7 | import java.security.KeyFactory; 8 | import java.security.NoSuchAlgorithmException; 9 | import java.security.PublicKey; 10 | import java.security.spec.InvalidKeySpecException; 11 | import java.security.spec.X509EncodedKeySpec; 12 | import java.util.Base64; 13 | 14 | public class SPacketEncryptionRequest extends AuthPacket { 15 | 16 | public PublicKey publicKey; 17 | public byte[] randomBytes; 18 | @Override 19 | public void handle(AuthWebsocket websocket) { 20 | websocket.handleEncryptionRequest(this); 21 | } 22 | 23 | @Override 24 | public String getName() { 25 | return "SPacketEncryptionRequest"; 26 | } 27 | 28 | public void getFromJson(JsonObject jsonObject){ 29 | Base64.Decoder decoder = Base64.getUrlDecoder(); 30 | this.publicKey =getPublicKey(decoder.decode(jsonObject.get("publicKey").getAsString())); 31 | this.randomBytes = decoder.decode(jsonObject.get("randomBytes").getAsString()); 32 | 33 | } 34 | @Override 35 | public void handle1(Object var1) { 36 | this.getFromJson(((JsonObject) var1)); 37 | } 38 | 39 | @Override 40 | public void handle2(Object var1) { 41 | this.getFromJson(((JsonObject) var1)); 42 | } 43 | 44 | public PublicKey getPublicKey(byte[] key){ 45 | X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key); 46 | try { 47 | KeyFactory kf = KeyFactory.getInstance("RSA"); 48 | return kf.generatePublic(x509EncodedKeySpec); 49 | } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { 50 | e.printStackTrace(); 51 | } 52 | return null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/util/AuthUtil.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.util; 2 | 3 | import com.mojang.authlib.Agent; 4 | import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; 5 | import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; 6 | 7 | import java.net.Proxy; 8 | 9 | public class AuthUtil { 10 | 11 | public static YggdrasilUserAuthentication getAuth(final String username, final String password) { 12 | final YggdrasilAuthenticationService service = new YggdrasilAuthenticationService(Proxy.NO_PROXY, ""); 13 | final YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) service.createUserAuthentication(Agent.MINECRAFT); 14 | auth.setUsername(username); 15 | auth.setPassword(password); 16 | try { 17 | auth.logIn(); 18 | return auth; 19 | } catch (com.mojang.authlib.exceptions.AuthenticationException localAuthenticationException) { 20 | localAuthenticationException.printStackTrace(); 21 | return null; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/util/ByteBufWrapper.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.util; 2 | 3 | import com.google.common.base.Charsets; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.buffer.ByteBufUtil; 6 | 7 | import java.io.IOException; 8 | import java.util.UUID; 9 | import java.util.function.Consumer; 10 | import java.util.function.Supplier; 11 | 12 | public class ByteBufWrapper { 13 | 14 | private final ByteBuf buf; 15 | 16 | public ByteBufWrapper(ByteBuf buf) { 17 | this.buf = buf; 18 | } 19 | 20 | public void writeVarInt(int b) { 21 | while ((b & 0xFFFFFF80) != 0x0) { 22 | this.buf.writeByte((b & 0x7F) | 0x80); 23 | b >>>= 7; 24 | } 25 | this.buf.writeByte(b); 26 | } 27 | 28 | public int readVarInt() { 29 | int i = 0; 30 | int chunk = 0; 31 | byte b; 32 | do { 33 | b = this.buf.readByte(); 34 | i |= (b & 0x7F) << chunk++ * 7; 35 | if (chunk > 5) { 36 | throw new RuntimeException("VarInt too big"); 37 | } 38 | } while ((b & 0x80) == 0x80); 39 | return i; 40 | } 41 | 42 | public String readStringFromBuffer(int p_150789_1_) throws IOException { 43 | int var2 = this.readVarInt(); 44 | 45 | if (var2 > p_150789_1_ * 4) { 46 | throw new IOException("The received encoded string buffer length is longer than maximum allowed (" + var2 + " > " + p_150789_1_ * 4 + ")"); 47 | } else if (var2 < 0) { 48 | throw new IOException("The received encoded string buffer length is less than zero! Weird string!"); 49 | } else { 50 | String var3 = new String(ByteBufUtil.getBytes(this.buf.readBytes(var2)), Charsets.UTF_8); 51 | 52 | if (var3.length() > p_150789_1_) { 53 | throw new IOException("The received string length is longer than maximum allowed (" + var2 + " > " + p_150789_1_ + ")"); 54 | } else { 55 | return var3; 56 | } 57 | } 58 | } 59 | 60 | public void writeOptional(T obj, Consumer consumer) { 61 | this.buf.writeBoolean(obj != null); 62 | if (obj != null) { 63 | consumer.accept(obj); 64 | } 65 | } 66 | 67 | public T readOptional(Supplier supplier) { 68 | boolean isPresent = this.buf.readBoolean(); 69 | return isPresent ? supplier.get() : null; 70 | } 71 | 72 | public void writeString(String s) { 73 | byte[] arr = s.getBytes(Charsets.UTF_8); 74 | this.writeVarInt(arr.length); 75 | this.buf.writeBytes(arr); 76 | } 77 | 78 | public String readString() { 79 | int len = this.readVarInt(); 80 | byte[] buffer = new byte[len]; 81 | this.buf.readBytes(buffer); 82 | return new String(buffer, Charsets.UTF_8); 83 | } 84 | 85 | public void writeUUID(UUID uuid) { 86 | this.buf.writeLong(uuid.getMostSignificantBits()); 87 | this.buf.writeLong(uuid.getLeastSignificantBits()); 88 | } 89 | 90 | public UUID readUUID() { 91 | long mostSigBits = this.buf.readLong(); 92 | long leastSigBits = this.buf.readLong(); 93 | return new UUID(mostSigBits, leastSigBits); 94 | } 95 | 96 | public ByteBuf buf() { 97 | return this.buf; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/util/Config.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.util; 2 | 3 | import lombok.Getter; 4 | 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.Properties; 9 | 10 | @Getter 11 | public class Config { 12 | private String uuid; 13 | private String username; 14 | private String email; 15 | private String password; 16 | 17 | public Config(){ 18 | Properties properties = new Properties(); 19 | InputStream inputStream = null; 20 | try{ 21 | inputStream = new FileInputStream("config.properties"); 22 | properties.load(inputStream); 23 | 24 | this.uuid = properties.getProperty("uuid"); 25 | this.username = properties.getProperty("user"); 26 | this.email = properties.getProperty("email"); 27 | this.password = properties.getProperty("password"); 28 | }catch (Exception ignored){} 29 | finally { 30 | if (inputStream != null) { 31 | try { 32 | inputStream.close(); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/me/pringles/lcwebsocketclient/util/CryptManager.java: -------------------------------------------------------------------------------- 1 | package me.pringles.lcwebsocketclient.util; 2 | 3 | 4 | 5 | import javax.crypto.*; 6 | import javax.crypto.spec.IvParameterSpec; 7 | import javax.crypto.spec.SecretKeySpec; 8 | import java.io.UnsupportedEncodingException; 9 | import java.security.*; 10 | import java.security.spec.EncodedKeySpec; 11 | import java.security.spec.InvalidKeySpecException; 12 | import java.security.spec.X509EncodedKeySpec; 13 | 14 | public class CryptManager 15 | { 16 | 17 | /** 18 | * Generate a new shared secret AES key from a secure random source 19 | */ 20 | public static SecretKey createNewSharedKey() 21 | { 22 | try 23 | { 24 | KeyGenerator keygenerator = KeyGenerator.getInstance("AES"); 25 | keygenerator.init(128); 26 | return keygenerator.generateKey(); 27 | } 28 | catch (NoSuchAlgorithmException nosuchalgorithmexception) 29 | { 30 | throw new Error(nosuchalgorithmexception); 31 | } 32 | } 33 | 34 | /** 35 | * Generates RSA KeyPair 36 | */ 37 | public static KeyPair generateKeyPair() 38 | { 39 | try 40 | { 41 | KeyPairGenerator keypairgenerator = KeyPairGenerator.getInstance("RSA"); 42 | keypairgenerator.initialize(1024); 43 | return keypairgenerator.generateKeyPair(); 44 | } 45 | catch (NoSuchAlgorithmException nosuchalgorithmexception) 46 | { 47 | nosuchalgorithmexception.printStackTrace(); 48 | return null; 49 | } 50 | } 51 | 52 | /** 53 | * Compute a serverId hash for use by sendSessionRequest() 54 | */ 55 | public static byte[] getServerIdHash(String serverId, PublicKey publicKey, SecretKey secretKey) 56 | { 57 | try 58 | { 59 | return digestOperation("SHA-1", serverId.getBytes("ISO_8859_1"), secretKey.getEncoded(), publicKey.getEncoded()); 60 | } 61 | catch (UnsupportedEncodingException unsupportedencodingexception) 62 | { 63 | unsupportedencodingexception.printStackTrace(); 64 | return null; 65 | } 66 | } 67 | 68 | /** 69 | * Compute a message digest on arbitrary byte[] data 70 | */ 71 | private static byte[] digestOperation(String algorithm, byte[]... data) 72 | { 73 | try 74 | { 75 | MessageDigest messagedigest = MessageDigest.getInstance(algorithm); 76 | 77 | for (byte[] abyte : data) 78 | { 79 | messagedigest.update(abyte); 80 | } 81 | 82 | return messagedigest.digest(); 83 | } 84 | catch (NoSuchAlgorithmException nosuchalgorithmexception) 85 | { 86 | nosuchalgorithmexception.printStackTrace(); 87 | return null; 88 | } 89 | } 90 | 91 | /** 92 | * Create a new PublicKey from encoded X.509 data 93 | */ 94 | public static PublicKey decodePublicKey(byte[] encodedKey) 95 | { 96 | try 97 | { 98 | EncodedKeySpec encodedkeyspec = new X509EncodedKeySpec(encodedKey); 99 | KeyFactory keyfactory = KeyFactory.getInstance("RSA"); 100 | return keyfactory.generatePublic(encodedkeyspec); 101 | } 102 | catch (NoSuchAlgorithmException var3) 103 | { 104 | ; 105 | } 106 | catch (InvalidKeySpecException var4) 107 | { 108 | ; 109 | } 110 | 111 | return null; 112 | } 113 | 114 | /** 115 | * Decrypt shared secret AES key using RSA private key 116 | */ 117 | public static SecretKey decryptSharedKey(PrivateKey key, byte[] secretKeyEncrypted) 118 | { 119 | return new SecretKeySpec(decryptData(key, secretKeyEncrypted), "AES"); 120 | } 121 | 122 | /** 123 | * Encrypt byte[] data with RSA public key 124 | */ 125 | public static byte[] encryptData(Key key, byte[] data) 126 | { 127 | return cipherOperation(1, key, data); 128 | } 129 | 130 | /** 131 | * Decrypt byte[] data with RSA private key 132 | */ 133 | public static byte[] decryptData(Key key, byte[] data) 134 | { 135 | return cipherOperation(2, key, data); 136 | } 137 | 138 | /** 139 | * Encrypt or decrypt byte[] data using the specified key 140 | */ 141 | private static byte[] cipherOperation(int opMode, Key key, byte[] data) 142 | { 143 | try 144 | { 145 | return createTheCipherInstance(opMode, key.getAlgorithm(), key).doFinal(data); 146 | } 147 | catch (IllegalBlockSizeException illegalblocksizeexception) 148 | { 149 | illegalblocksizeexception.printStackTrace(); 150 | } 151 | catch (BadPaddingException badpaddingexception) 152 | { 153 | badpaddingexception.printStackTrace(); 154 | } 155 | 156 | return null; 157 | } 158 | 159 | /** 160 | * Creates the Cipher Instance. 161 | */ 162 | private static Cipher createTheCipherInstance(int opMode, String transformation, Key key) 163 | { 164 | try 165 | { 166 | Cipher cipher = Cipher.getInstance(transformation); 167 | cipher.init(opMode, key); 168 | return cipher; 169 | } 170 | catch (InvalidKeyException invalidkeyexception) 171 | { 172 | invalidkeyexception.printStackTrace(); 173 | } 174 | catch (NoSuchAlgorithmException nosuchalgorithmexception) 175 | { 176 | nosuchalgorithmexception.printStackTrace(); 177 | } 178 | catch (NoSuchPaddingException nosuchpaddingexception) 179 | { 180 | nosuchpaddingexception.printStackTrace(); 181 | } 182 | 183 | return null; 184 | } 185 | 186 | /** 187 | * Creates an Cipher instance using the AES/CFB8/NoPadding algorithm. Used for protocol encryption. 188 | */ 189 | public static Cipher createNetCipherInstance(int opMode, Key key) 190 | { 191 | try 192 | { 193 | Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding"); 194 | cipher.init(opMode, key, new IvParameterSpec(key.getEncoded())); 195 | return cipher; 196 | } 197 | catch (GeneralSecurityException generalsecurityexception) 198 | { 199 | throw new RuntimeException(generalsecurityexception); 200 | } 201 | } 202 | } 203 | --------------------------------------------------------------------------------