This repository was archived by the owner on Oct 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Attestation
amplitudes edited this page Apr 14, 2023
·
6 revisions
Attestation allows you to securely verify a user's device using cryptography.
public final class APITest extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
}
private List<UUID> expecting = new ArrayList<>();
private HashMap<UUID, X509EncodedKeySpec> keys = new HashMap<>();
private HashMap<UUID, byte[]> validationData = new HashMap<>();
@EventHandler
public void onPlayerChatMessage(PlayerCommandPreprocessEvent event) { // Simple example, so we're not going to make a proper command handler.
Player player = event.getPlayer();
String message = event.getMessage();
if (message.equalsIgnoreCase("/register") || message.equalsIgnoreCase("/auth")) {
event.setCancelled(true);
} else {
return;
}
ECServerAPI serverAPI = ECServerAPI.getInstance();
if (event.getMessage().equalsIgnoreCase("/register")) {
player.sendMessage(ChatColor.GREEN + "Registering your device...");
expecting.add(player.getUniqueId());
serverAPI.sendPacket(player, new OutAttestationRegister());
} else if (event.getMessage().equalsIgnoreCase("/auth")) {
if (!keys.containsKey(player.getUniqueId())) {
player.sendMessage(ChatColor.RED + "You have not yet registered your device.");
return;
}
player.sendMessage(ChatColor.GREEN + "Authenticating your device...");
byte[] data = new byte[512];
try {
SecureRandom.getInstanceStrong().nextBytes(data);
} catch (NoSuchAlgorithmException e) {
player.sendMessage(ChatColor.RED + "Failed to generate random data.");
return;
}
validationData.put(player.getUniqueId(), data);
serverAPI.sendPacket(player, new OutAttestationSign(data));
}
}
@EventHandler
public void onEmberAttestationResult(EmberAttestationRegisterEvent event) {
Player player = event.getPlayer();
UUID playerUUID = player.getUniqueId();
if (!expecting.contains(playerUUID)) {
player.sendMessage(ChatColor.RED + "Failed to register public key: You have not requested a registration.");
return;
}
expecting.remove(playerUUID);
if (!event.getStatus().equals(AttestationRegisterResult.SUCCESS)) {
player.sendMessage(ChatColor.RED + "Failed to register device: " + event.getStatus().name());
return;
}
keys.put(playerUUID, event.getPublicKey());
player.sendMessage(ChatColor.GREEN + "Successfully registered device.");
}
@EventHandler
public void onEmberAttestationSign(EmberAttestationSignEvent event) {
Player player = event.getPlayer();
UUID playerUUID = player.getUniqueId();
if (!validationData.containsKey(playerUUID)) {
player.sendMessage(ChatColor.RED + "Failed to verify data: You have not requested verification.");
return;
}
byte[] data = validationData.get(playerUUID);
validationData.remove(playerUUID);
if (!event.getStatus().equals(AttestationSignResult.SUCCESS)) {
player.sendMessage(ChatColor.RED + "Failed to sign data: " + event.getStatus().name());
return;
}
try {
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify(KeyFactory.getInstance("RSA").generatePublic(keys.get(event.getPlayer().getUniqueId())));
sig.update(data);
if (!sig.verify(event.getSignedData())) {
event.getPlayer().sendMessage(ChatColor.RED + "Failed to verify attestation: Signature mismatch.");
return;
}
event.getPlayer().sendMessage(ChatColor.GREEN + "Successfully verified attestation.");
} catch (Exception e) {
event.getPlayer().sendMessage(ChatColor.RED + "Failed to verify attestation: " + e.getMessage());
}
}
}