mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2025-01-08 09:27:34 +01:00
expand and document WrappedProfilePublicKey (#1618)
This commit is contained in:
parent
868b357527
commit
d7bf43001f
@ -1,13 +1,23 @@
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PublicKey;
|
||||
import java.time.Instant;
|
||||
import java.util.Base64;
|
||||
import java.util.Base64.Encoder;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* A wrapper around the profile public key.
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
public class WrappedProfilePublicKey extends AbstractWrapper {
|
||||
|
||||
private static final Class<?> HANDLE_TYPE = MinecraftReflection.getProfilePublicKeyClass();
|
||||
@ -16,65 +26,177 @@ public class WrappedProfilePublicKey extends AbstractWrapper {
|
||||
private static final ConstructorAccessor CONSTRUCTOR = Accessors.getConstructorAccessor(HANDLE_TYPE, KEY_DATA_TYPE);
|
||||
private static final FieldAccessor DATA_ACCESSOR = Accessors.getFieldAccessor(HANDLE_TYPE, KEY_DATA_TYPE, true);
|
||||
|
||||
// lazy initialized when needed
|
||||
private static FieldAccessor PROFILE_KEY_ACCESSOR;
|
||||
|
||||
/**
|
||||
* Constructs a new profile public key wrapper directly from a nms ProfilePublicKey object.
|
||||
*
|
||||
* @param handle the handle to create the wrapper from.
|
||||
*/
|
||||
public WrappedProfilePublicKey(Object handle) {
|
||||
super(HANDLE_TYPE);
|
||||
this.setHandle(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new profile public key wrapper holding the given key data.
|
||||
*
|
||||
* @param keyData the data of the key.
|
||||
*/
|
||||
public WrappedProfilePublicKey(WrappedProfileKeyData keyData) {
|
||||
this(CONSTRUCTOR.invoke(keyData.getHandle()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the profile public key from the given player instance.
|
||||
*
|
||||
* @param player the player to get the key of.
|
||||
* @return a wrapper around the public key of the given player.
|
||||
*/
|
||||
public static WrappedProfilePublicKey ofPlayer(Player player) {
|
||||
FieldAccessor accessor = PROFILE_KEY_ACCESSOR;
|
||||
if (accessor == null) {
|
||||
accessor = Accessors.getFieldAccessor(MinecraftReflection.getEntityHumanClass(), HANDLE_TYPE, true);
|
||||
PROFILE_KEY_ACCESSOR = accessor;
|
||||
}
|
||||
|
||||
Object nmsPlayer = BukkitUnwrapper.getInstance().unwrapItem(player);
|
||||
return new WrappedProfilePublicKey(accessor.get(nmsPlayer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a wrapper around the key data stored in this public key.
|
||||
*
|
||||
* @return the data of this key.
|
||||
*/
|
||||
public WrappedProfileKeyData getKeyData() {
|
||||
return new WrappedProfileKeyData(DATA_ACCESSOR.get(this.getHandle()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data of this key. Note that changing the key data might lead to unexpected issues with the server, for
|
||||
* example chat message validation to fail.
|
||||
*
|
||||
* @param keyData the new data of this key.
|
||||
*/
|
||||
public void setKeyData(WrappedProfileKeyData keyData) {
|
||||
DATA_ACCESSOR.set(this.getHandle(), keyData.getHandle());
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper around the data stored in a profile key.
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
public static class WrappedProfileKeyData extends AbstractWrapper {
|
||||
|
||||
private static final ConstructorAccessor CONSTRUCTOR = Accessors.getConstructorAccessor(
|
||||
KEY_DATA_TYPE,
|
||||
Instant.class, PublicKey.class, byte[].class);
|
||||
private static final Encoder MIME_ENCODER = Base64.getMimeEncoder(76, "\n".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
private final StructureModifier<Object> modifier;
|
||||
|
||||
/**
|
||||
* Constructs a new key data instance directly from the given nms KeyData object.
|
||||
*
|
||||
* @param handle the handle to create the wrapper from.
|
||||
*/
|
||||
public WrappedProfileKeyData(Object handle) {
|
||||
super(KEY_DATA_TYPE);
|
||||
this.setHandle(handle);
|
||||
this.modifier = new StructureModifier<>(KEY_DATA_TYPE).withTarget(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new data wrapper instance using the given parameters.
|
||||
*
|
||||
* @param expireTime the instant when the key data expires.
|
||||
* @param key the public key used to verify incoming data.
|
||||
* @param signature the signature of the public key.
|
||||
*/
|
||||
public WrappedProfileKeyData(Instant expireTime, PublicKey key, byte[] signature) {
|
||||
this(CONSTRUCTOR.invoke(expireTime, key, signature));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time instant when this key data expires.
|
||||
*
|
||||
* @return the time instant when this key data expires.
|
||||
*/
|
||||
public Instant getExpireTime() {
|
||||
return this.modifier.<Instant>withType(Instant.class).read(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time when this key data expires.
|
||||
*
|
||||
* @param expireTime the new time when this key data expires.
|
||||
*/
|
||||
public void setExpireTime(Instant expireTime) {
|
||||
this.modifier.<Instant>withType(Instant.class).write(0, expireTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this key data is expired.
|
||||
*
|
||||
* @return true if this key data is expired, false otherwise.
|
||||
*/
|
||||
public boolean isExpired() {
|
||||
return this.getExpireTime().isBefore(Instant.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the signed payload of this key data. The signature of this data must verify against the payload data of
|
||||
* the key. If it does not, the key data is considered unsigned.
|
||||
* <p>
|
||||
* Note that this method takes the expiry time of the key into accountability, if this key is expired it will no
|
||||
* longer match the key data signature.
|
||||
*
|
||||
* @return the signed payload version of this profile key data.
|
||||
*/
|
||||
public String getSignedPayload() {
|
||||
String rsaString = "-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
+ MIME_ENCODER.encodeToString(this.getKey().getEncoded())
|
||||
+ "\n-----END RSA PUBLIC KEY-----\n";
|
||||
return this.getExpireTime().toEpochMilli() + rsaString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the public key of this key data.
|
||||
*
|
||||
* @return the public key of this key data.
|
||||
*/
|
||||
public PublicKey getKey() {
|
||||
return this.modifier.<PublicKey>withType(PublicKey.class).read(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the public key of this key data.
|
||||
*
|
||||
* @param key the new public key of this key data.
|
||||
*/
|
||||
public void setKey(PublicKey key) {
|
||||
this.modifier.<PublicKey>withType(PublicKey.class).write(0, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the signature of this key data.
|
||||
*
|
||||
* @return the key data of this signature.
|
||||
* @see #getSignedPayload()
|
||||
*/
|
||||
public byte[] getSignature() {
|
||||
return this.modifier.<byte[]>withType(byte[].class).read(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the signature of this key data.
|
||||
*
|
||||
* @param signature the new signature of this key data.
|
||||
* @see #getSignedPayload()
|
||||
*/
|
||||
public void setSignature(byte[] signature) {
|
||||
this.modifier.<byte[]>withType(byte[].class).write(0, signature);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user