allow keeping the same trypt instance for a while, massively improving security of chatcrypt
This commit is contained in:
parent
d3a7346ece
commit
c8ea8ae662
3 changed files with 68 additions and 14 deletions
|
@ -2,8 +2,10 @@ package com.baseband.client.module.chat;
|
||||||
|
|
||||||
import com.baseband.client.configuration.annotation.Config;
|
import com.baseband.client.configuration.annotation.Config;
|
||||||
import com.baseband.client.configuration.annotation.Gate;
|
import com.baseband.client.configuration.annotation.Gate;
|
||||||
|
import com.baseband.client.configuration.annotation.MultiGate;
|
||||||
import com.baseband.client.configuration.annotation.Range;
|
import com.baseband.client.configuration.annotation.Range;
|
||||||
import com.baseband.client.event.events.PacketEvent;
|
import com.baseband.client.event.events.PacketEvent;
|
||||||
|
import com.baseband.client.gui.lib.component.Button;
|
||||||
import com.baseband.client.mixins.ICPacketChat;
|
import com.baseband.client.mixins.ICPacketChat;
|
||||||
import com.baseband.client.module.Feature;
|
import com.baseband.client.module.Feature;
|
||||||
import com.baseband.client.module.category.Chat;
|
import com.baseband.client.module.category.Chat;
|
||||||
|
@ -49,10 +51,12 @@ public class ChatCrypt extends Feature {
|
||||||
@Config("Use SBE algorithm (preferred)")
|
@Config("Use SBE algorithm (preferred)")
|
||||||
@Marker(1)
|
@Marker(1)
|
||||||
public boolean useSBE = true;
|
public boolean useSBE = true;
|
||||||
|
@Marker(2)
|
||||||
|
public boolean useTrypt = false;
|
||||||
|
|
||||||
@Config("(But Trypt looks more random)")
|
@Config("(But Trypt looks more random)")
|
||||||
@Marker(2)
|
@Marker(-1)
|
||||||
@Gate(2)
|
@Gate(-1)
|
||||||
public boolean _trypt_info = true;
|
public boolean _trypt_info = true;
|
||||||
|
|
||||||
@Config("Seed")
|
@Config("Seed")
|
||||||
|
@ -64,13 +68,29 @@ public class ChatCrypt extends Feature {
|
||||||
@Gate(1)
|
@Gate(1)
|
||||||
public int boxSize = 256;
|
public int boxSize = 256;
|
||||||
|
|
||||||
|
@Config("Keep Trypt instance")
|
||||||
|
@Gate(2)
|
||||||
|
@Marker(3)
|
||||||
|
public boolean keepTrypt = false;
|
||||||
|
|
||||||
|
@Config("Warning! More secure, worse QOL")
|
||||||
|
@MultiGate(and = {3, -2})
|
||||||
|
@Marker(-2)
|
||||||
|
public boolean _keep_info = true;
|
||||||
|
|
||||||
|
@Config("Reset Trypt")
|
||||||
|
@Gate(3)
|
||||||
|
public Button.ClickEvent resetTrypt = btn -> {
|
||||||
|
trypt = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
private Trypt trypt;
|
||||||
|
|
||||||
private final Pattern CHAT_PATTERN = Pattern.compile("(<.*?> )|(.*?: )");
|
private final Pattern CHAT_PATTERN = Pattern.compile("(<.*?> )|(.*?: )");
|
||||||
|
|
||||||
@Config("Password")
|
@Config("Password")
|
||||||
public String password = "CLICK HERE";
|
public String password = "CLICK HERE";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
if(password.isEmpty() || password.equalsIgnoreCase("CLICK HERE")) {
|
if(password.isEmpty() || password.equalsIgnoreCase("CLICK HERE")) {
|
||||||
toggle();
|
toggle();
|
||||||
|
@ -78,6 +98,12 @@ public class ChatCrypt extends Feature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEveryTick() {
|
||||||
|
useTrypt = !useSBE;
|
||||||
|
}
|
||||||
|
|
||||||
|
String sentSomething = null;
|
||||||
|
|
||||||
public void onPacketRead(PacketEvent.Read e) {
|
public void onPacketRead(PacketEvent.Read e) {
|
||||||
if (e.getPacket() instanceof SPacketChat) {
|
if (e.getPacket() instanceof SPacketChat) {
|
||||||
|
@ -97,8 +123,23 @@ public class ChatCrypt extends Feature {
|
||||||
message = message.substring(0, message.length() - getTerminator().length());
|
message = message.substring(0, message.length() - getTerminator().length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isOurs = message.equals(sentSomething);
|
||||||
|
sentSomething = null;
|
||||||
|
|
||||||
GlobalUtil.LOGGER.info("decrypt: {}", message);
|
GlobalUtil.LOGGER.info("decrypt: {}", message);
|
||||||
message = decrypt(message);
|
byte[] original = recoverBytes(message);
|
||||||
|
message = decrypt(original);
|
||||||
|
|
||||||
|
if(!useSBE && keepTrypt && !isOurs) {
|
||||||
|
// we must re-encrypt anything we get, unless it is from ourselves, to make sure our key stays up-to-date
|
||||||
|
if(Arrays.equals(trypt.encryptChunk(message.getBytes(StandardCharsets.UTF_8), original[0]), original)) {
|
||||||
|
GlobalUtil.LOGGER.debug("Successfully kept Trypt key up-to-date.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
HUD.notifyAndPrint("§c§lChat>§c Unable to keep Trypt key up-to-date. You must reset it.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FieldFinder.findUnmarked(SPacketChat.class, ITextComponent.class, 0).set(e.getPacket(), new TextComponentString("§dChatCrypt> §r" + username + ": " + message));
|
FieldFinder.findUnmarked(SPacketChat.class, ITextComponent.class, 0).set(e.getPacket(), new TextComponentString("§dChatCrypt> §r" + username + ": " + message));
|
||||||
} catch (IllegalAccessException ex) {
|
} catch (IllegalAccessException ex) {
|
||||||
|
@ -127,10 +168,13 @@ public class ChatCrypt extends Feature {
|
||||||
if(s.startsWith("/"))
|
if(s.startsWith("/"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s = encrypt(s) + getTerminator();
|
s = encrypt(s);
|
||||||
|
sentSomething = s;
|
||||||
|
s += getTerminator();
|
||||||
if (s.length() > 256) {
|
if (s.length() > 256) {
|
||||||
ChatUtil.print("Encrypted message length was too long, couldn't send!");
|
ChatUtil.print("Encrypted message length was too long, couldn't send!");
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
|
sentSomething = null;
|
||||||
}
|
}
|
||||||
((ICPacketChat)e.getPacket()).setMessage(s);
|
((ICPacketChat)e.getPacket()).setMessage(s);
|
||||||
}
|
}
|
||||||
|
@ -142,20 +186,22 @@ public class ChatCrypt extends Feature {
|
||||||
return armorBytes(sbe.transform(value.getBytes(StandardCharsets.UTF_8)));
|
return armorBytes(sbe.transform(value.getBytes(StandardCharsets.UTF_8)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Trypt trypt = new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8));
|
if(!keepTrypt || trypt == null)
|
||||||
|
trypt = new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8));
|
||||||
return armorBytes(trypt.encryptChunk(value.getBytes(StandardCharsets.UTF_8)));
|
return armorBytes(trypt.encryptChunk(value.getBytes(StandardCharsets.UTF_8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String decrypt(String encrypted) {
|
public String decrypt(byte[] encrypted) {
|
||||||
if(useSBE) {
|
if(useSBE) {
|
||||||
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
|
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
|
||||||
return new String(sbe.transform(recoverBytes(encrypted)), StandardCharsets.US_ASCII);
|
return new String(sbe.transform(encrypted), StandardCharsets.US_ASCII);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Trypt trypt = new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8));
|
if(!keepTrypt || trypt == null)
|
||||||
return new String(trypt.decryptChunk(recoverBytes(encrypted)), StandardCharsets.UTF_8);
|
trypt = new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8));
|
||||||
|
return new String(trypt.decryptChunk(encrypted), StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.baseband.client.module.Category;
|
||||||
import com.baseband.client.module.Feature;
|
import com.baseband.client.module.Feature;
|
||||||
import com.baseband.client.module.category.Render;
|
import com.baseband.client.module.category.Render;
|
||||||
import com.baseband.client.module.client.Client;
|
import com.baseband.client.module.client.Client;
|
||||||
|
import com.baseband.client.util.ingame.ChatUtil;
|
||||||
import com.baseband.client.util.misc.Marker;
|
import com.baseband.client.util.misc.Marker;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.Gui;
|
import net.minecraft.client.gui.Gui;
|
||||||
|
@ -50,6 +51,11 @@ public class HUD extends Feature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void notifyAndPrint(String text) {
|
||||||
|
notifs.add(new Notification(text));
|
||||||
|
ChatUtil.print(text);
|
||||||
|
}
|
||||||
|
|
||||||
public static void notify(String text) {
|
public static void notify(String text) {
|
||||||
notifs.add(new Notification(text));
|
notifs.add(new Notification(text));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,18 @@ public class Trypt {
|
||||||
cRandD = new Random(seed);
|
cRandD = new Random(seed);
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] encryptChunk(byte[] input) {
|
public byte[] encryptChunk(byte[] input) {
|
||||||
|
return encryptChunk(input, (byte) sRand.nextInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] encryptChunk(byte[] input, byte salt) {
|
||||||
ArrayList<Byte> data = new ArrayList<>(input.length);
|
ArrayList<Byte> data = new ArrayList<>(input.length);
|
||||||
for (byte b : input) {
|
for (byte b : input) {
|
||||||
data.add(b);
|
data.add(b);
|
||||||
}
|
}
|
||||||
ArrayList<Integer> forbidden = new ArrayList<>(input.length);
|
ArrayList<Integer> forbidden = new ArrayList<>(input.length);
|
||||||
byte[] output = new byte[input.length + 1];
|
byte[] output = new byte[input.length + 1];
|
||||||
byte salt = (byte) sRand.nextInt();
|
|
||||||
output[0] = salt;
|
output[0] = salt;
|
||||||
|
|
||||||
for(int i = 0; i < input.length;) {
|
for(int i = 0; i < input.length;) {
|
||||||
|
@ -36,7 +39,6 @@ public class Trypt {
|
||||||
forbidden.add(newLocation);
|
forbidden.add(newLocation);
|
||||||
byte old = data.remove(0);
|
byte old = data.remove(0);
|
||||||
output[newLocation + 1] = (byte) (old ^ salt ^ key[(i++ ^ cRandE.nextInt(0x7fffffff)) % key.length]);
|
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)));
|
salt = (byte) (salt ^ (newLocation << cRandE.nextInt(8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue