2025-11-24 22:52:51 +03:00

126 lines
5.1 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.mojang.logging.LogUtils
* org.jspecify.annotations.Nullable
* org.slf4j.Logger
*/
package net.minecraft.network.chat;
import com.mojang.logging.LogUtils;
import java.time.Instant;
import java.util.UUID;
import java.util.function.BooleanSupplier;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FilterMask;
import net.minecraft.network.chat.MessageSignature;
import net.minecraft.network.chat.PlayerChatMessage;
import net.minecraft.network.chat.SignedMessageBody;
import net.minecraft.network.chat.SignedMessageLink;
import net.minecraft.network.chat.ThrowingComponent;
import net.minecraft.util.SignatureValidator;
import net.minecraft.util.Signer;
import net.minecraft.world.entity.player.ProfilePublicKey;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public class SignedMessageChain {
private static final Logger LOGGER = LogUtils.getLogger();
private @Nullable SignedMessageLink nextLink;
private Instant lastTimeStamp = Instant.EPOCH;
public SignedMessageChain(UUID profileId, UUID sessionId) {
this.nextLink = SignedMessageLink.root(profileId, sessionId);
}
public Encoder encoder(Signer signer) {
return body -> {
SignedMessageLink link = this.nextLink;
if (link == null) {
return null;
}
this.nextLink = link.advance();
return new MessageSignature(signer.sign(output -> PlayerChatMessage.updateSignature(output, link, body)));
};
}
public Decoder decoder(final ProfilePublicKey profilePublicKey) {
final SignatureValidator signatureValidator = profilePublicKey.createSignatureValidator();
return new Decoder(){
@Override
public PlayerChatMessage unpack(@Nullable MessageSignature signature, SignedMessageBody body) throws DecodeException {
if (signature == null) {
throw new DecodeException(DecodeException.MISSING_PROFILE_KEY);
}
if (profilePublicKey.data().hasExpired()) {
throw new DecodeException(DecodeException.EXPIRED_PROFILE_KEY);
}
SignedMessageLink link = SignedMessageChain.this.nextLink;
if (link == null) {
throw new DecodeException(DecodeException.CHAIN_BROKEN);
}
if (body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) {
this.setChainBroken();
throw new DecodeException(DecodeException.OUT_OF_ORDER_CHAT);
}
SignedMessageChain.this.lastTimeStamp = body.timeStamp();
PlayerChatMessage unpacked = new PlayerChatMessage(link, signature, body, null, FilterMask.PASS_THROUGH);
if (!unpacked.verify(signatureValidator)) {
this.setChainBroken();
throw new DecodeException(DecodeException.INVALID_SIGNATURE);
}
if (unpacked.hasExpiredServer(Instant.now())) {
LOGGER.warn("Received expired chat: '{}'. Is the client/server system time unsynchronized?", (Object)body.content());
}
SignedMessageChain.this.nextLink = link.advance();
return unpacked;
}
@Override
public void setChainBroken() {
SignedMessageChain.this.nextLink = null;
}
};
}
@FunctionalInterface
public static interface Encoder {
public static final Encoder UNSIGNED = body -> null;
public @Nullable MessageSignature pack(SignedMessageBody var1);
}
public static class DecodeException
extends ThrowingComponent {
private static final Component MISSING_PROFILE_KEY = Component.translatable("chat.disabled.missingProfileKey");
private static final Component CHAIN_BROKEN = Component.translatable("chat.disabled.chain_broken");
private static final Component EXPIRED_PROFILE_KEY = Component.translatable("chat.disabled.expiredProfileKey");
private static final Component INVALID_SIGNATURE = Component.translatable("chat.disabled.invalid_signature");
private static final Component OUT_OF_ORDER_CHAT = Component.translatable("chat.disabled.out_of_order_chat");
public DecodeException(Component component) {
super(component);
}
}
@FunctionalInterface
public static interface Decoder {
public static Decoder unsigned(UUID profileId, BooleanSupplier enforcesSecureChat) {
return (signature, body) -> {
if (enforcesSecureChat.getAsBoolean()) {
throw new DecodeException(DecodeException.MISSING_PROFILE_KEY);
}
return PlayerChatMessage.unsigned(profileId, body.content());
};
}
public PlayerChatMessage unpack(@Nullable MessageSignature var1, SignedMessageBody var2) throws DecodeException;
default public void setChainBroken() {
}
}
}