chatcrypt improvements, show toggle notifs

This commit is contained in:
Daniella / Tove 2024-05-25 00:13:11 +02:00
parent ae8d9a8201
commit 06c187ca96
7 changed files with 226 additions and 46 deletions

View file

@ -60,7 +60,7 @@ public class EventManager {
try {
method.invoke(subscriber, event);
} catch (Exception e) {
GlobalUtil.LOGGER.error(e.getStackTrace());
e.printStackTrace();
}
}
}

View file

@ -71,7 +71,6 @@ public class BaseBand {
new Thread(() -> {
while (true) {
for (Updater updater : updaters) {
GlobalUtil.LOGGER.debug("Polling - " + updater.toString());
updater.poll();
}
try {

View file

@ -7,6 +7,7 @@ import com.baseband.client.init.BaseBand;
import com.baseband.client.configuration.ConfigHandle;
import com.baseband.client.configuration.Configuration;
import com.baseband.client.module.category.Command;
import com.baseband.client.module.render.HUD;
import com.baseband.client.util.misc.FieldFinder;
import com.baseband.client.util.config.KeyBind;
import com.baseband.client.util.misc.Marker;
@ -80,10 +81,12 @@ public abstract class Feature extends ToggleButton implements SetCommand {
BaseBand.eventManager.subscribe(this);
MinecraftForge.EVENT_BUS.register(this);
onEnable();
HUD.notify("§l" + this + "§a enabled§r.");
} else {
BaseBand.eventManager.unsubscribe(this);
MinecraftForge.EVENT_BUS.unregister(this);
onDisable();
HUD.notify("§l" + this + "§c disabled§r.");
}
}
@ -216,15 +219,7 @@ public abstract class Feature extends ToggleButton implements SetCommand {
public void toggle() {
enabled = !enabled;
if(enabled) {
BaseBand.eventManager.subscribe(this);
MinecraftForge.EVENT_BUS.register(this);
onEnable();
} else {
BaseBand.eventManager.unsubscribe(this);
MinecraftForge.EVENT_BUS.unregister(this);
onDisable();
}
updateEnabled();
handle.poll("Enabled");
}

View file

@ -1,18 +1,24 @@
package com.baseband.client.module.chat;
import com.baseband.client.configuration.annotation.Config;
import com.baseband.client.configuration.annotation.Gate;
import com.baseband.client.configuration.annotation.Range;
import com.baseband.client.event.events.PacketEvent;
import com.baseband.client.mixins.ICPacketChat;
import com.baseband.client.module.Feature;
import com.baseband.client.module.category.Chat;
import com.baseband.client.module.render.HUD;
import com.baseband.client.util.ingame.ChatUtil;
import com.baseband.client.util.misc.SBE;
import com.baseband.client.util.misc.*;
import de.tudbut.tools.Hasher;
import net.minecraft.network.play.client.CPacketChatMessage;
import net.minecraft.network.play.server.SPacketChat;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -23,18 +29,42 @@ public class ChatCrypt extends Feature {
return "ChatCrypt";
}
public enum NotifMode {
Client,
Chat,
Both,
}
public enum EncryptMode {
SBE,
Trypt,
}
@Config("Notification mode")
public NotifMode mode = NotifMode.Chat;
@Config("Send")
public boolean send;
@Config("Use SBE algorithm (preferred)")
@Marker(1)
public boolean useSBE = true;
@Config("(But Trypt looks more random)")
@Marker(2)
@Gate(2)
public boolean _trypt_info = true;
@Config("Seed")
@Range("256..4096")
@Range("-4096..4096")
public int seed = 256;
@Config("Box Size")
@Range("256..4096")
@Gate(1)
public int boxSize = 256;
private final Pattern CHAT_PATTERN = Pattern.compile("<.*?> ");
private final Pattern CHAT_PATTERN = Pattern.compile("(<.*?> )|(.*?: )");
@Config("Password")
public String password = "CLICK HERE";
@ -67,9 +97,20 @@ public class ChatCrypt extends Feature {
message = message.substring(0, message.length() - getTerminator().length());
}
GlobalUtil.LOGGER.info("decrypt: {}", message);
message = decrypt(message);
try {
FieldFinder.findUnmarked(SPacketChat.class, ITextComponent.class, 0).set(e.getPacket(), new TextComponentString("§dChatCrypt> §r" + username + ": " + message));
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
ChatUtil.print("[ChatCrypt] " + username + ": " + message);
switch (mode) {
case Client:
e.setCancelled(true);
case Both:
HUD.notify("§dChat> §r" + username + ": " + message, 15000);
}
}
}
@ -96,30 +137,69 @@ public class ChatCrypt extends Feature {
}
public String encrypt(String value) {
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
return bytesToHex(sbe.transform(value.getBytes(StandardCharsets.US_ASCII)));
if(useSBE) {
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
return armorBytes(sbe.transform(value.getBytes(StandardCharsets.UTF_8)));
}
else {
Trypt trypt = new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8));
return armorBytes(trypt.encryptChunk(value.getBytes(StandardCharsets.UTF_8)));
}
}
public String decrypt(String encrypted) {
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
return new String(sbe.transform(hexToBytes(encrypted)), StandardCharsets.US_ASCII);
}
public String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
hexString.append(String.format("%02x", b));
if(useSBE) {
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
return new String(sbe.transform(recoverBytes(encrypted)), StandardCharsets.US_ASCII);
}
else {
Trypt trypt = new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8));
return new String(trypt.decryptChunk(recoverBytes(encrypted)), StandardCharsets.UTF_8);
}
return hexString.toString();
}
public byte[] hexToBytes(String hexString) {
int length = hexString.length();
byte[] bytes = new byte[length / 2];
for (int i = 0; i < length; i += 2) {
bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
char[] table = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~¡¢£¥¦«²³¹»ÆÇÈÉÊÑÒÓÖÙÚÜßàáäåæçèéêñòóö×".toCharArray();
byte[] rtable = new byte[256];
{
for (int i = 0; i < 128; i++) {
rtable[table[i]] = (byte) i;
}
}
public String armorBytes(byte[] bytes) {
StringBuilder s = new StringBuilder();
ArrayList<Byte> accums = new ArrayList<>();
byte accum = 0;
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
s.append(table[Byte.toUnsignedInt(b) >> 1]);
accum = (byte) (accum + (b & 1));
accum = (byte) (((b & 1) << 6) + (accum >> 1));
if(i % 7 == 6) {
accums.add(accum);
accum = 0;
}
}
accum = (byte) (accum >> (7 - bytes.length % 7));
s.append(table[accum]);
for (int i = accums.size() - 1; i >= 0; i--) {
s.append(table[accums.get(i)]);
}
return s.toString();
}
public byte[] recoverBytes(String armored) {
char[] chars = armored.toCharArray();
byte[] bytes = new byte[chars.length - ((chars.length - 1) / 8 + 1)];
byte accum = rtable[chars[chars.length - 1]];
for (int i = 0, r = 1; i < bytes.length; i++) {
byte b = (byte) ((rtable[chars[i]] << 1) + (accum & 1));
accum = (byte) (accum >> 1);
bytes[i] = b;
if(i % 7 == 6) {
accum = rtable[chars[chars.length - ++r]];
}
}
return bytes;
}

View file

@ -11,6 +11,7 @@ import com.baseband.client.util.misc.Marker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@ -37,6 +38,16 @@ public class HUD extends Feature {
this.text = text;
this.time = ms;
}
public float opacity(int sensitivity) {
long elapsed = System.currentTimeMillis() - start;
long timeLeft = (time - elapsed) / sensitivity;
return Math.min(1f, timeLeft / Math.min(time / 10f, 500f));
}
public int opacity(int n, int sensitivity) {
return Math.max(1, (int) (n * opacity(sensitivity)));
}
}
public static void notify(String text) {
@ -104,7 +115,7 @@ public class HUD extends Feature {
public void text(RenderGameOverlayEvent.Text e) {
ScaledResolution sr = new ScaledResolution(mc);
mc.fontRenderer.drawStringWithShadow("BaseBand - \"" + BaseBand.buildString + "\"", 2,2, BaseBand.getModule(Client.class).getTheme().getGreenColor());
mc.fontRenderer.drawStringWithShadow("§lBaseBand§r - \"" + BaseBand.buildString + "\"", 2,2, BaseBand.getModule(Client.class).getTheme().getGreenColor());
int y = 11;
for (Feature f : Arrays.stream(Setup.Features).filter(m -> m.enabled && m.category != Category.COMMAND && m.category != Category.CLIENT && !m.toString().equals("HUD")).sorted(Comparator.comparingDouble(value -> -Minecraft.getMinecraft().fontRenderer.getStringWidth(value.toString()))).toArray(Feature[]::new)) {
mc.fontRenderer.drawStringWithShadow(f.toString(), 2, y, BaseBand.getModule(Client.class).getTheme().getGreenColor());
@ -112,9 +123,11 @@ public class HUD extends Feature {
}
if(notifications) {
int dir = (nLocation == NotificationLocation.Center ? -1 : 1);
int isCenter = (nLocation == NotificationLocation.Center ? 1 : 0);
int xSize = this.nSize * 100;
int ySize = this.nVSize * 10;
int textOffset = (ySize / 2 - (9 / 2));
int textOffset = (ySize / 2 - (mc.fontRenderer.FONT_HEIGHT / 2));
int x = 2;
if(nLocation == NotificationLocation.Center) {
x = sr.getScaledWidth() / 2 - (xSize / 2);
@ -131,27 +144,56 @@ public class HUD extends Feature {
Notification[] notifs = HUD.notifs.toArray(new Notification[0]);
for (int i = notifs.length - 1; i >= 0; i--) {
Notification notif = notifs[i];
Gui.drawRect(x, y, x + xSize, y + ySize, 0x80202040);
int localYSize = ySize;
String text = notif.text;
if(mc.fontRenderer.getStringWidth(text) > xSize - textOffset * 2) {
while(mc.fontRenderer.getStringWidth(text) > xSize - textOffset * 2 - 5) {
text = text.substring(0, text.length() - 1);
while(getStringWidth(text) > xSize - textOffset * 2) {
StringBuilder nextLine = new StringBuilder();
while(getStringWidth(text) > xSize - textOffset * 2) {
int h = text.lastIndexOf(' ');
if(h == -1)
h = text.length() - 1;
nextLine.insert(0, text.substring(h));
text = text.substring(0, h);
}
text += "...";
text += "\n" + nextLine;
localYSize += mc.fontRenderer.FONT_HEIGHT;
}
drawStringL(text, x + textOffset, y + textOffset, 0xffffffff);
y += (ySize + nVSpace) * (nLocation == NotificationLocation.Center ? -1 : 1);
int textboxYSize = localYSize;
localYSize = notif.opacity(localYSize, 1);
drawSizedBox(x, y, xSize, localYSize, 0x202040 + (notif.opacity(0x80, 1) << 24), isCenter == 1);
GlStateManager.enableBlend();
drawStringL(text, x + textOffset, y + textOffset - isCenter * textboxYSize, 0xffffff + (Math.max(8, notif.opacity(0xff, 2)) << 24), notif.opacity(2) == 1.0);
GlStateManager.disableBlend();
y += (localYSize + nVSpace) * dir;
}
}
}
private void drawString(String s, int x, int y, int color) {
drawStringL(s, x - mc.fontRenderer.getStringWidth(s), y, color);
private void drawSizedBox(int x, int y, int sx, int sy, int color, boolean backwards) {
Gui.drawRect(x, y, x + sx, y + sy * (backwards ? -1 : 1), color);
}
private void drawStringL(String s, int x, int y, int color) {
mc.fontRenderer.drawStringWithShadow(s, (float)x, (float)y, color);
private int getStringWidth(String text) {
int w = 0;
for (String s : text.split("\n")) {
int width = mc.fontRenderer.getStringWidth(s);
if(width > w)
w = width;
}
return w;
}
private void drawString(String s, int x, int y, int color, boolean shadow) {
drawStringL(s, x - getStringWidth(s), y, color, shadow);
}
private void drawStringL(String s, int x, int y, int color, boolean shadow) {
String[] split = s.split("\n");
for (int i = 0; i < split.length; i++) {
mc.fontRenderer.drawString(split[i], (float) x, (float) y + mc.fontRenderer.FONT_HEIGHT * i, color, shadow);
}
}
}

View file

@ -36,7 +36,7 @@ public class SBE {
for (int i = 0; i < blocks.length; i++) {
byte[] b1 = blocks[i];
for (int j = 0; j < b1.length; j++) {
b1[j] = (byte) (b1[j] ^ (this.key[i] ^ box[(i * j) % box.length]));
b1[j] = (byte) (b1[j] ^ (this.key[i] ^ box[(i + j) % box.length]));
}
}

View file

@ -0,0 +1,64 @@
package com.baseband.client.util.misc;
import de.tudbut.tools.StringTools;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
public class Trypt {
SecureRandom sRand = new SecureRandom();
Random cRandE;
Random cRandD;
byte[] key;
public Trypt(long seed, byte[] key) {
cRandE = new Random(seed);
cRandD = new Random(seed);
this.key = key;
}
public byte[] encryptChunk(byte[] input) {
ArrayList<Byte> data = new ArrayList<>(input.length);
for (byte b : input) {
data.add(b);
}
ArrayList<Integer> forbidden = new ArrayList<>(input.length);
byte[] output = new byte[input.length + 1];
byte salt = (byte) sRand.nextInt();
output[0] = salt;
for(int i = 0; i < input.length;) {
int newLocation = cRandE.nextInt(input.length);
if(forbidden.contains(newLocation))
continue;
forbidden.add(newLocation);
byte old = data.remove(0);
output[newLocation + 1] = (byte) (old ^ salt ^ key[(i++ ^ cRandE.nextInt(0x7fffffff)) % key.length]);
//input[(newLocation + 1) % input.length] -= (byte) (old ^ cRandE.nextInt(0x7fffffff));
salt = (byte) (salt ^ (newLocation << cRandE.nextInt(8)));
}
return output;
}
public byte[] decryptChunk(byte[] input) {
ArrayList<Integer> forbidden = new ArrayList<>(input.length);
byte[] output = new byte[input.length - 1];
byte salt = input[0];
for (int i = 0; i < output.length;) {
int newLocation = cRandD.nextInt(output.length);
if(forbidden.contains(newLocation))
continue;
forbidden.add(newLocation);
byte encrypted = input[newLocation + 1];
byte old = (byte) (encrypted ^ salt ^ key[(i ^ cRandD.nextInt(0x7fffffff)) % key.length]);
output[i++] += old;
salt = (byte) (salt ^ (newLocation << cRandD.nextInt(8)));
}
return output;
}
}