Added wrappers for MessageSignature (#2362)

This commit is contained in:
Lukas Alt 2023-05-01 05:28:19 +02:00 committed by GitHub
parent 08ea2da642
commit 2931af58db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 33 deletions

View File

@ -1017,7 +1017,7 @@ public abstract class AbstractStructure {
} }
/** /**
* @return read/writer structure direct access to signature data like chat messages * @return read/writer structure direct access to salted signature data like chat messages
*/ */
public StructureModifier<WrappedSaltedSignature> getSignatures() { public StructureModifier<WrappedSaltedSignature> getSignatures() {
return structureModifier.withType( return structureModifier.withType(
@ -1026,6 +1026,16 @@ public abstract class AbstractStructure {
); );
} }
/**
* @return read/writer structure direct access to unsalted signature data for example in chat message (since 1.19.3)
*/
public StructureModifier<WrappedMessageSignature> getMessageSignatures() {
return structureModifier.withType(
MinecraftReflection.getMessageSignatureClass(),
BukkitConverters.getWrappedMessageSignatureConverter()
);
}
/** /**
* @param leftConverter converter for left values * @param leftConverter converter for left values
* @param rightConverter converter for right values * @param rightConverter converter for right values

View File

@ -1573,6 +1573,10 @@ public final class MinecraftReflection {
return getMinecraftClass("world.entity.player.ProfilePublicKey"); return getMinecraftClass("world.entity.player.ProfilePublicKey");
} }
public static Class<?> getMessageSignatureClass() {
return getMinecraftClass("network.chat.MessageSignature");
}
public static Class<?> getSaltedSignatureClass() { public static Class<?> getSaltedSignatureClass() {
try { try {
return getMinecraftClass("SaltedSignature"); return getMinecraftClass("SaltedSignature");

View File

@ -615,6 +615,13 @@ public class BukkitConverters {
return ignoreNull(handle(WrappedSaltedSignature::getHandle, WrappedSaltedSignature::new, WrappedSaltedSignature.class)); return ignoreNull(handle(WrappedSaltedSignature::getHandle, WrappedSaltedSignature::new, WrappedSaltedSignature.class));
} }
/**
* @return converter for an encoded cryptographic message signature
*/
public static EquivalentConverter<WrappedMessageSignature> getWrappedMessageSignatureConverter() {
return ignoreNull(handle(WrappedMessageSignature::getHandle, WrappedMessageSignature::new, WrappedMessageSignature.class));
}
public static EquivalentConverter<WrappedLevelChunkData.ChunkData> getWrappedChunkDataConverter() { public static EquivalentConverter<WrappedLevelChunkData.ChunkData> getWrappedChunkDataConverter() {
return ignoreNull(handle(WrappedLevelChunkData.ChunkData::getHandle, WrappedLevelChunkData.ChunkData::new, WrappedLevelChunkData.ChunkData.class)); return ignoreNull(handle(WrappedLevelChunkData.ChunkData::getHandle, WrappedLevelChunkData.ChunkData::new, WrappedLevelChunkData.ChunkData.class));
} }

View File

@ -0,0 +1,48 @@
package com.comphenix.protocol.wrappers;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
import com.comphenix.protocol.utility.MinecraftReflection;
/**
* @author Lukas Alt
* @since 24.04.2023
*/
public class WrappedMessageSignature extends AbstractWrapper {
private final static Class<?> HANDLE_TYPE = MinecraftReflection.getMessageSignatureClass();
private static ConstructorAccessor CONSTRUCTOR;
private StructureModifier<Object> modifier;
/**
* Construct a new NMS wrapper.
*
* @param handle - the NMS handle
*/
public WrappedMessageSignature(Object handle) {
super(HANDLE_TYPE);
this.setHandle(handle);
}
public WrappedMessageSignature(byte[] bytes) {
super(HANDLE_TYPE);
if(CONSTRUCTOR == null) {
CONSTRUCTOR = Accessors.getConstructorAccessor(HANDLE_TYPE, byte[].class);
}
this.setHandle(CONSTRUCTOR.invoke(bytes));
}
@Override
protected void setHandle(Object handle) {
super.setHandle(handle);
this.modifier = new StructureModifier<>(HANDLE_TYPE).withTarget(handle);
}
public byte[] getBytes() {
return modifier.<byte[]>withType(byte[].class).read(0);
}
public void setBytes(byte[] bytes) {
modifier.<byte[]>withType(byte[].class).write(0, bytes);
}
}

View File

@ -774,21 +774,17 @@ public class PacketContainerTest {
Assertions.assertEquals(NativeGameMode.CREATIVE, firstData.getGameMode()); Assertions.assertEquals(NativeGameMode.CREATIVE, firstData.getGameMode());
} }
// TODO: fix this this at some point
/*
@Test @Test
public void testSignedChatMessage() { public void testSignedChatMessage() {
PacketContainer chatPacket = new PacketContainer(PacketType.Play.Client.CHAT); PacketContainer chatPacket = new PacketContainer(PacketType.Play.Client.CHAT);
byte[] signature = new byte[512]; byte[] signature = new byte[256];
long salt = 124L; WrappedMessageSignature wrappedSignature = new WrappedMessageSignature(signature);
WrappedSaltedSignature wrappedSignature = new WrappedSaltedSignature(salt, signature); chatPacket.getMessageSignatures().write(0, wrappedSignature);
chatPacket.getSignatures().write(0, wrappedSignature);
WrappedSaltedSignature read = chatPacket.getSignatures().read(0); WrappedMessageSignature read = chatPacket.getMessageSignatures().read(0);
assertEquals(salt, read.getSalt()); assertArrayEquals(signature, read.getBytes());
assertArrayEquals(signature, read.getSignature()); }
}*/
private void assertPacketsEqualAndSerializable(PacketContainer constructed, PacketContainer cloned) { private void assertPacketsEqualAndSerializable(PacketContainer constructed, PacketContainer cloned) {
StructureModifier<Object> firstMod = constructed.getModifier(), secondMod = cloned.getModifier(); StructureModifier<Object> firstMod = constructed.getModifier(), secondMod = cloned.getModifier();

View File

@ -16,18 +16,9 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.util.Random; import java.util.Random;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class BukkitConvertersTest { public class BukkitConvertersTest {
@ -69,18 +60,27 @@ public class BukkitConvertersTest {
assertEquals(wrapped.right(), nmsEither.right()); assertEquals(wrapped.right(), nmsEither.right());
} }
@Test @Test
public void testPacketContainerConverter() { public void testPacketContainerConverter() {
for (PacketType type : PacketType.values()) { for (PacketType type : PacketType.values()) {
if (!type.isSupported()) { if(!type.isSupported()) {
continue; continue;
} }
PacketContainer container = new PacketContainer(type); PacketContainer container = new PacketContainer(type);
Object generic = BukkitConverters.getPacketContainerConverter().getGeneric(container); Object generic = BukkitConverters.getPacketContainerConverter().getGeneric(container);
Object specific = BukkitConverters.getPacketContainerConverter().getSpecific(generic); Object specific = BukkitConverters.getPacketContainerConverter().getSpecific(generic);
assertTrue(EqualsBuilder.reflectionEquals(container, specific)); // PacketContainer does not properly implement equals(.) assertTrue(EqualsBuilder.reflectionEquals(container, specific)); // PacketContainer does not properly implement equals(.)
} }
} }
@Test
void getWrappedMessageSignatureConverter() {
byte[] data = new byte[256];
new Random().nextBytes(data);
WrappedMessageSignature messageSignature = new WrappedMessageSignature(data);
assertArrayEquals(data, BukkitConverters.getWrappedMessageSignatureConverter().getSpecific(BukkitConverters.getWrappedMessageSignatureConverter().getGeneric(messageSignature)).getBytes());
}
@Test @Test
public void testRemoteChatSessionDataConverter() throws Exception { public void testRemoteChatSessionDataConverter() throws Exception {