add password hashing and commands
This commit is contained in:
parent
1b61f085e3
commit
ec0a1aa5c3
9 changed files with 148 additions and 19 deletions
|
@ -67,8 +67,8 @@ public class GuiForm extends Gui implements ButtonCallback {
|
||||||
GuiForm.this.labels[index].setText(name);
|
GuiForm.this.labels[index].setText(name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.inputs[z] = this.add((param & 0x80000000) != 0 ? new PasswordField(0, 50 * z, 300, 24, Math.min(param & 0xffff, 256), callback, (String)obj) :
|
this.inputs[z] = this.add((param & 0x80000000) != 0 ? new PasswordField(0, 50 * z, 300, 24, Math.min(param & 0xffff, 1024), callback, (String)obj) :
|
||||||
new Field(0, 50 * z, 300, 24, Math.min(param & 0xffff, 256), callback, (String)obj));
|
new Field(0, 50 * z, 300, 24, Math.min(param & 0xffff, 1024), callback, (String)obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.add(new NavButton(0, 50 * (this.inputs.length + 1), 148, 24, null, "Abbrechen"));
|
this.add(new NavButton(0, 50 * (this.inputs.length + 1), 148, 24, null, "Abbrechen"));
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class CPacketForm implements Packet<IPlayer>
|
||||||
obj = buf.readVarInt();
|
obj = buf.readVarInt();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
obj = buf.readString(256);
|
obj = buf.readString(1024);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.data[z] = obj;
|
this.data[z] = obj;
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class RPacketServerConfig implements Packet<IClientLoginHandler> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAuthenticating() {
|
public boolean isAuthenticating() {
|
||||||
return this.passwordAuth;
|
return this.requiresAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canUsePassword() {
|
public boolean canUsePassword() {
|
||||||
|
|
|
@ -10,9 +10,11 @@ import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.security.spec.AlgorithmParameterSpec;
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
import java.security.spec.EncodedKeySpec;
|
import java.security.spec.EncodedKeySpec;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.KeySpec;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -24,7 +26,9 @@ import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.KeyGenerator;
|
import javax.crypto.KeyGenerator;
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import common.log.Log;
|
import common.log.Log;
|
||||||
|
@ -189,6 +193,7 @@ public class EncryptUtil {
|
||||||
|
|
||||||
private static final long CRC24_INIT = 0xB704CEL;
|
private static final long CRC24_INIT = 0xB704CEL;
|
||||||
private static final long CRC24_POLY = 0x1864CFBL;
|
private static final long CRC24_POLY = 0x1864CFBL;
|
||||||
|
private static final byte[] CLIENT_SALT = "ItIsSaltySalt2765666 tftffs ##89n!.le98udMeowHAsh44m;+*3m9DI9Sqn".getBytes();
|
||||||
|
|
||||||
private static byte[] crc24(byte[] data) {
|
private static byte[] crc24(byte[] data) {
|
||||||
long crc = CRC24_INIT;
|
long crc = CRC24_INIT;
|
||||||
|
@ -203,4 +208,23 @@ public class EncryptUtil {
|
||||||
int value = (int)(crc & 0xFFFFFFL);
|
int value = (int)(crc & 0xFFFFFFL);
|
||||||
return new byte[] {(byte)((value >> 16) & 0xff), (byte)((value >> 8) & 0xff), (byte)(value & 0xff)};
|
return new byte[] {(byte)((value >> 16) & 0xff), (byte)((value >> 8) & 0xff), (byte)(value & 0xff)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] hashPassword(String password, byte[] salt) {
|
||||||
|
try {
|
||||||
|
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
|
||||||
|
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||||
|
return factory.generateSecret(spec).getEncoded();
|
||||||
|
}
|
||||||
|
catch(NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||||
|
Log.SYSTEM.error(e, "Konnte Passwort-Prüfwert nicht errechnen");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<byte[], byte[]> hashPassword(String password) {
|
||||||
|
SecureRandom rand = new SecureRandom();
|
||||||
|
byte[] salt = new byte[64];
|
||||||
|
rand.nextBytes(salt);
|
||||||
|
return new Pair<byte[], byte[]>(hashPassword(password, salt), salt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -854,7 +855,7 @@ public final class Server implements IThreadListener {
|
||||||
if(tag != null)
|
if(tag != null)
|
||||||
conn.readTags(tag);
|
conn.readTags(tag);
|
||||||
if(Config.authenticate) {
|
if(Config.authenticate) {
|
||||||
if(conn.getPassword() == null && conn.getPubkey() == null) {
|
if(conn.getPasswordHash() == null && conn.getPubkey() == null) {
|
||||||
if(tag != null)
|
if(tag != null)
|
||||||
return loginKey != null ? "Falscher Pubkey" : "Falsches Passwort";
|
return loginKey != null ? "Falscher Pubkey" : "Falsches Passwort";
|
||||||
if(!Config.register)
|
if(!Config.register)
|
||||||
|
@ -870,11 +871,12 @@ public final class Server implements IThreadListener {
|
||||||
return "Ein neues Passwort ist erforderlich um diesen Server zu betreten (mindestens " + Config.minPassLength + " Zeichen)";
|
return "Ein neues Passwort ist erforderlich um diesen Server zu betreten (mindestens " + Config.minPassLength + " Zeichen)";
|
||||||
if(loginPass.length() < Config.minPassLength)
|
if(loginPass.length() < Config.minPassLength)
|
||||||
return "Passwort ist zu kurz, mindestens " + Config.minPassLength + " Zeichen";
|
return "Passwort ist zu kurz, mindestens " + Config.minPassLength + " Zeichen";
|
||||||
conn.setPassword(loginPass);
|
conn.setPasswordHash(EncryptUtil.hashPassword(loginPass));
|
||||||
Log.NETWORK.info(loginUser + " registrierte sich mit Passwort");
|
Log.NETWORK.info(loginUser + " registrierte sich mit Passwort");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(conn.getPubkey() != null ? !conn.getPubkey().equals(loginKey) : !conn.getPassword().equals(loginPass)) {
|
else if(conn.getPubkey() != null ? !conn.getPubkey().equals(loginKey) :
|
||||||
|
(loginPass == null || !MessageDigest.isEqual(EncryptUtil.hashPassword(loginPass, conn.getPasswordHash().second()), conn.getPasswordHash().first()))) {
|
||||||
return loginKey != null ? "Falscher Pubkey" : "Falsches Passwort";
|
return loginKey != null ? "Falscher Pubkey" : "Falsches Passwort";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import server.command.commands.CommandOfflinetp;
|
||||||
import server.command.commands.CommandPasswd;
|
import server.command.commands.CommandPasswd;
|
||||||
import server.command.commands.CommandPlayers;
|
import server.command.commands.CommandPlayers;
|
||||||
import server.command.commands.CommandPotion;
|
import server.command.commands.CommandPotion;
|
||||||
|
import server.command.commands.CommandPubkey;
|
||||||
import server.command.commands.CommandRegister;
|
import server.command.commands.CommandRegister;
|
||||||
import server.command.commands.CommandRemove;
|
import server.command.commands.CommandRemove;
|
||||||
import server.command.commands.CommandRevoke;
|
import server.command.commands.CommandRevoke;
|
||||||
|
@ -280,6 +281,7 @@ public class CommandEnvironment {
|
||||||
this.registerExecutable(new CommandMessage());
|
this.registerExecutable(new CommandMessage());
|
||||||
this.registerExecutable(new CommandShutdown());
|
this.registerExecutable(new CommandShutdown());
|
||||||
this.registerExecutable(new CommandPasswd());
|
this.registerExecutable(new CommandPasswd());
|
||||||
|
this.registerExecutable(new CommandPubkey());
|
||||||
this.registerExecutable(new CommandPlayers());
|
this.registerExecutable(new CommandPlayers());
|
||||||
this.registerExecutable(new CommandSave());
|
this.registerExecutable(new CommandSave());
|
||||||
this.registerExecutable(new CommandRegister());
|
this.registerExecutable(new CommandRegister());
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package server.command.commands;
|
package server.command.commands;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
import common.color.TextColor;
|
import common.color.TextColor;
|
||||||
import common.init.Config;
|
import common.init.Config;
|
||||||
import common.network.IPlayer;
|
import common.network.IPlayer;
|
||||||
|
import common.util.EncryptUtil;
|
||||||
import server.command.Command;
|
import server.command.Command;
|
||||||
import server.command.CommandEnvironment;
|
import server.command.CommandEnvironment;
|
||||||
import server.command.Executor;
|
import server.command.Executor;
|
||||||
|
@ -25,6 +28,10 @@ public class CommandPasswd extends Command {
|
||||||
throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden");
|
throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden");
|
||||||
if(player.getAdmin() && player != exec)
|
if(player.getAdmin() && player != exec)
|
||||||
throw new RunException("%s ist ein Admin", player.getUser());
|
throw new RunException("%s ist ein Admin", player.getUser());
|
||||||
|
if(player.getPubkey() != null && player == exec)
|
||||||
|
throw new RunException("Es darf kein Pubkey vorhanden sein, um diesen Befehl an sich selbst anzuwenden");
|
||||||
|
if(player.getPasswordHash() == null && player == exec)
|
||||||
|
throw new RunException("Es muss ein Passwort vorhanden sein, um diesen Befehl an sich selbst anzuwenden");
|
||||||
((Player)exec).displayForm(new Form() {
|
((Player)exec).displayForm(new Form() {
|
||||||
private Field checkField;
|
private Field checkField;
|
||||||
private Field passwordField;
|
private Field passwordField;
|
||||||
|
@ -42,11 +49,11 @@ public class CommandPasswd extends Command {
|
||||||
|
|
||||||
protected void accept() {
|
protected void accept() {
|
||||||
Player plr = env.getServer().getPlayer(player.getUser());
|
Player plr = env.getServer().getPlayer(player.getUser());
|
||||||
if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec)) {
|
if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec) || (plr.getPasswordHash() == null && plr == exec) || (plr.getPubkey() != null && plr == exec)) {
|
||||||
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
|
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(this.checkField != null && !this.checkField.get().equals(plr.getPassword())) {
|
if(this.checkField != null && !MessageDigest.isEqual(EncryptUtil.hashPassword(this.checkField.get(), plr.getPasswordHash().second()), plr.getPasswordHash().first())) {
|
||||||
exec.logConsole(TextColor.RED + "Falsches Passwort eingegeben");
|
exec.logConsole(TextColor.RED + "Falsches Passwort eingegeben");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +61,8 @@ public class CommandPasswd extends Command {
|
||||||
exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein");
|
exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
plr.setPassword(this.passwordField.get());
|
plr.setPasswordHash(EncryptUtil.hashPassword(this.passwordField.get()));
|
||||||
|
plr.setPubkey(null);
|
||||||
exec.logConsole(TextColor.GREEN + "Passwort" + (plr != exec ? " für %s" : "") + " gesetzt", plr.getUser());
|
exec.logConsole(TextColor.GREEN + "Passwort" + (plr != exec ? " für %s" : "") + " gesetzt", plr.getUser());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -62,7 +70,10 @@ public class CommandPasswd extends Command {
|
||||||
else if(exec.isConsole()) {
|
else if(exec.isConsole()) {
|
||||||
if(password == null)
|
if(password == null)
|
||||||
throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden");
|
throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden");
|
||||||
player.setPassword(password);
|
if(password.length() < 8)
|
||||||
|
throw new RunException("Das Passwort ist zu kurz, mindestens 8 Zeichen sind erforderlich");
|
||||||
|
player.setPasswordHash(EncryptUtil.hashPassword(password));
|
||||||
|
player.setPubkey(null);
|
||||||
exec.logConsole(TextColor.GREEN + "Passwort für %s gesetzt", player.getUser());
|
exec.logConsole(TextColor.GREEN + "Passwort für %s gesetzt", player.getUser());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
package server.command.commands;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
|
||||||
|
import common.color.TextColor;
|
||||||
|
import common.network.IPlayer;
|
||||||
|
import common.util.EncryptUtil;
|
||||||
|
import common.util.Pair;
|
||||||
|
import server.command.Command;
|
||||||
|
import server.command.CommandEnvironment;
|
||||||
|
import server.command.Executor;
|
||||||
|
import server.command.RunException;
|
||||||
|
import server.network.Player;
|
||||||
|
import server.util.Form;
|
||||||
|
|
||||||
|
public class CommandPubkey extends Command {
|
||||||
|
public CommandPubkey() {
|
||||||
|
super("pubkey");
|
||||||
|
|
||||||
|
this.addPlayer("player", true);
|
||||||
|
this.setParamsOptional();
|
||||||
|
this.addString("keySpec", false);
|
||||||
|
this.addString("keyData", false);
|
||||||
|
this.addString("keyHash", false);
|
||||||
|
this.addString("keyName", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exec(CommandEnvironment env, Executor exec, Player player, String keySpec, String keyData, String keyHash, String keyName) {
|
||||||
|
if(exec.isPlayer()) {
|
||||||
|
if(keySpec != null || keyData != null || keyHash != null || keyName != null)
|
||||||
|
throw new RunException("Bei Verwendung als Spieler darf kein Schlüssel angegeben werden");
|
||||||
|
if(player.getAdmin() && player != exec)
|
||||||
|
throw new RunException("%s ist ein Admin", player.getUser());
|
||||||
|
((Player)exec).displayForm(new Form() {
|
||||||
|
private Field checkField;
|
||||||
|
private Field keyField;
|
||||||
|
|
||||||
|
protected void init() {
|
||||||
|
this.checkField = player.getPasswordHash() == null || player != exec ? null : this.addPassword("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, "");
|
||||||
|
this.keyField = this.addField("Neuer Pubkey", 1, 960, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return "Schlüssel für " + player.getUser() + " ändern";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void accept() {
|
||||||
|
Player plr = env.getServer().getPlayer(player.getUser());
|
||||||
|
if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec)) {
|
||||||
|
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(this.checkField != null && plr.getPasswordHash() != null && !MessageDigest.isEqual(EncryptUtil.hashPassword(this.checkField.get(), plr.getPasswordHash().second()), plr.getPasswordHash().first())) {
|
||||||
|
exec.logConsole(TextColor.RED + "Falsches Passwort eingegeben");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Pair<PublicKey, String> key;
|
||||||
|
try {
|
||||||
|
key = EncryptUtil.parseArmoredPubkey(this.keyField.get());
|
||||||
|
}
|
||||||
|
catch(IllegalArgumentException e) {
|
||||||
|
exec.logConsole(TextColor.RED + "Ungültiger Schlüssel");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
plr.setPasswordHash(null);
|
||||||
|
plr.setPubkey(key.first());
|
||||||
|
exec.logConsole(TextColor.GREEN + "Schlüssel" + (plr != exec ? " für %s" : "") + " gesetzt", plr.getUser());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if(exec.isConsole()) {
|
||||||
|
if(keySpec == null || keyData == null || keyHash == null)
|
||||||
|
throw new RunException("Bei Verwendung in der Konsole muss ein Schlüssel angegeben werden");
|
||||||
|
Pair<PublicKey, String> key;
|
||||||
|
try {
|
||||||
|
key = EncryptUtil.parseArmoredPubkey(keySpec + " " + keyData + " " + keyHash + (keyName == null ? null : " " + keyName));
|
||||||
|
}
|
||||||
|
catch(IllegalArgumentException e) {
|
||||||
|
throw new RunException(e, "Ungültiger Schlüssel");
|
||||||
|
}
|
||||||
|
player.setPasswordHash(null);
|
||||||
|
player.setPubkey(key.first());
|
||||||
|
exec.logConsole(TextColor.GREEN + "Schlüssel für %s gesetzt", player.getUser());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -115,6 +115,7 @@ import common.util.EncryptUtil;
|
||||||
import common.util.ExtMath;
|
import common.util.ExtMath;
|
||||||
import common.util.Facing;
|
import common.util.Facing;
|
||||||
import common.util.IntHashMap;
|
import common.util.IntHashMap;
|
||||||
|
import common.util.Pair;
|
||||||
import common.util.PortalType;
|
import common.util.PortalType;
|
||||||
import common.util.Position;
|
import common.util.Position;
|
||||||
import common.util.Vec3i;
|
import common.util.Vec3i;
|
||||||
|
@ -172,7 +173,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
|
||||||
private boolean admin;
|
private boolean admin;
|
||||||
private int ping;
|
private int ping;
|
||||||
private boolean deleted;
|
private boolean deleted;
|
||||||
private String password;
|
private Pair<byte[], byte[]> password;
|
||||||
private PublicKey pubkey;
|
private PublicKey pubkey;
|
||||||
private boolean profiling;
|
private boolean profiling;
|
||||||
|
|
||||||
|
@ -343,11 +344,11 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
|
||||||
return this.isAdmin();
|
return this.isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPassword(String pass) {
|
public void setPasswordHash(Pair<byte[], byte[]> hash) {
|
||||||
this.password = pass;
|
this.password = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public Pair<byte[], byte[]> getPasswordHash() {
|
||||||
return this.password;
|
return this.password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,8 +629,8 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
|
||||||
|
|
||||||
public void readTags(TagObject tag) {
|
public void readTags(TagObject tag) {
|
||||||
this.admin = tag.getBool("admin");
|
this.admin = tag.getBool("admin");
|
||||||
if(tag.hasString("password"))
|
if(tag.hasByteArray("passwordHash") && tag.hasByteArray("passwordSalt"))
|
||||||
this.password = tag.getString("password");
|
this.password = new Pair<byte[], byte[]>(tag.getByteArray("passwordHash"), tag.getByteArray("passwordSalt"));
|
||||||
if(tag.hasByteArray("pubkey"))
|
if(tag.hasByteArray("pubkey"))
|
||||||
this.pubkey = EncryptUtil.decodePublicKey(tag.getByteArray("pubkey"));
|
this.pubkey = EncryptUtil.decodePublicKey(tag.getByteArray("pubkey"));
|
||||||
this.selected = tag.getInt("selected");
|
this.selected = tag.getInt("selected");
|
||||||
|
@ -644,8 +645,10 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
|
||||||
public void writeTags(TagObject tag) {
|
public void writeTags(TagObject tag) {
|
||||||
if(this.admin)
|
if(this.admin)
|
||||||
tag.setBool("admin", this.admin);
|
tag.setBool("admin", this.admin);
|
||||||
if(this.password != null)
|
if(this.password != null) {
|
||||||
tag.setString("password", this.password);
|
tag.setByteArray("passwordHash", this.password.first());
|
||||||
|
tag.setByteArray("passwordSalt", this.password.second());
|
||||||
|
}
|
||||||
if(this.pubkey != null)
|
if(this.pubkey != null)
|
||||||
tag.setByteArray("pubkey", this.pubkey.getEncoded());
|
tag.setByteArray("pubkey", this.pubkey.getEncoded());
|
||||||
if(!this.characters.isEmpty()) {
|
if(!this.characters.isEmpty()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue