Added a RandomString class from stackoverflow, to generate random alphanumeric strings (to be used as passwords).

Added some code to VaultDoor, including random password generation and code to encrypt/decrypt under a Vernam-like cypher.
Modified door opening policy to include the possibility of keeping the door open.
This commit is contained in:
sg495 2018-01-08 20:40:50 +01:00
parent 9bb0dc9034
commit 46483b2bf8
4 changed files with 193 additions and 32 deletions

View File

@ -0,0 +1,16 @@
public class InvalidCharsetException extends Exception {
public InvalidCharsetException () {
}
public InvalidCharsetException (String message) {
super (message);
}
public InvalidCharsetException (Throwable cause) {
super (cause);
}
public InvalidCharsetException (String message, Throwable cause) {
super (message, cause);
}

View File

@ -0,0 +1,68 @@
/**
*
* RandomString class by erickson
* https://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string
*
*/
import java.security.SecureRandom;
import java.util.Locale;
import java.util.Objects;
import java.util.Random;
public class RandomString {
/**
* Generate a random string.
*/
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String lower = upper.toLowerCase(Locale.ROOT);
public static final String digits = "0123456789";
public static final String alphanum = upper + lower + digits;
private final Random random;
private final char[] symbols;
private final char[] buf;
public RandomString(int length, Random random, String symbols) {
if (length < 1) throw new IllegalArgumentException();
if (symbols.length() < 2) throw new IllegalArgumentException();
this.random = Objects.requireNonNull(random);
this.symbols = symbols.toCharArray();
this.buf = new char[length];
}
/**
* Create an alphanumeric string generator.
*/
public RandomString(int length, Random random) {
this(length, random, alphanum);
}
/**
* Create an alphanumeric strings from a secure generator.
*/
public RandomString(int length) {
this(length, new SecureRandom());
}
/**
* Create session identifiers.
*/
public RandomString() {
this(21);
}
}

View File

@ -6,6 +6,7 @@ import net.simon987.server.game.GameObject;
import net.simon987.server.game.Programmable; import net.simon987.server.game.Programmable;
import net.simon987.server.game.Updatable; import net.simon987.server.game.Updatable;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.vaultplugin.RandomString;
import java.util.Arrays; import java.util.Arrays;
@ -19,77 +20,148 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
*/ */
private char[] password; private char[] password;
private RandomString random_string_generator;
/** /**
* Whether or not the vault door is opened * Whether or not the vault door is opened
*/ */
private boolean opened; private boolean open = false;
private int openedTimer;
/** /**
* Number of ticks to remain the door open * Number of ticks to remain the door open
*/ */
private static final int OPEN_TIME = 4; //todo load from config private int OPEN_TIME = GameServer.INSTANCE.getConfig().getInt("vault_door_open_time");
private int openedTimer = 0;
private int password_length;
private int cypher_id;
public VaultDoor(int password_length, int cypher_id){
this.password_length = password_length;
this.cypher_id = cypher_id;
this.random_string_generator = new RandomString(password_length);
password = getRandomPassword();
}
@Override @Override
public void update() { public void update() {
if (open){
if (openedTimer <= 0) { if (openedTimer <= 0) {
//Door was open for OPEN_TIME, close it and regen password
//Door was opened for OPEN_TIME, close it and regen password
password = getRandomPassword(); password = getRandomPassword();
opened = false; open = false;
openedTimer = 0;
LogManager.LOGGER.fine("Closed Vault door ID: " + getObjectId()); LogManager.LOGGER.fine("Closed Vault door ID: " + getObjectId());
} else { }
else{
openedTimer--; openedTimer--;
} }
}
} }
@Override @Override
public boolean sendMessage(char[] message) { public boolean sendMessage(char[] message) {
System.out.println("VAULT: sendMessage" + new String(message));//todo rmv
if (!opened) {
if (Arrays.equals(message, password)) { if (Arrays.equals(message, password)) {
opened = true; if (!open) {
openedTimer = OPEN_TIME; openVault();
}
else{
keepVaultOpen();
}
return true;
}
else {
return false;
}
}
private void openVault(){
open = true;
openedTimer = OPEN_TIME;
LogManager.LOGGER.fine("Opened Vault door ID: " + getObjectId()); LogManager.LOGGER.fine("Opened Vault door ID: " + getObjectId());
} }
return true; private void keepVaultOpen(){
} else { open = true;
//Can't receive messages when opened openedTimer = OPEN_TIME;
return false;
}
} }
@Override @Override
public boolean enter(GameObject object) { public boolean enter(GameObject object) {
LogManager.LOGGER.fine("VAULT enter " + opened); LogManager.LOGGER.fine("VAULT enter " + open);
if (opened) {
if (open) {
//TODO: Enter in the vault //TODO: Enter in the vault
return true; return true;
} else { } else {
return false; return false;
} }
} }
/**
* Generates a random alphanumeric string using the RandomString class
*/
private static char[] getRandomPassword() { private static char[] getRandomPassword() {
return "12345678".toCharArray();//todo actual random password return random_string_generator.nextString().toCharArray();
} }
private char[] encryptVernam(char[] plaintext){
String charset = random_string_generator.alphanum;
int charset_length = charset.length();
int plaintext_length = plaintext.length;
char[] cyphertext = new char[plaintext_length];
for (int i = 0; i< plaintext_length; i++){
int j = i % password_length;
char p = plaintext[i];
char q = password[j];
int p_ind = charset.indexOf(p);
if (p_ind == -1){
throw InvalidCharsetException("Plaintext contains non-alphanumeric character: "+p);
}
int q_ind = charset.indexOf(q);
if (q_ind == -1){
throw InvalidCharsetException("Password contains non-alphanumeric character: "+q); // this should NEVER happen
}
int c_int = (p_ind+q_ind)%charset_length;
char c = charset.charAt(c_int);
cyphertext[i] = c;
}
return cyphertext;
}
private char[] decryptVernam(char[] cyphertext){
String charset = random_string_generator.alphanum;
int charset_length = charset.length();
int cyphertext_length = cyphertext.length;
char[] plaintext = new char[cyphertext_length];
for (int i = 0; i< cyphertext_length; i++){
int j = i % password_length;
char c = cyphertext[i];
char q = password[j];
int c_ind = charset.indexOf(c);
if (c_ind == -1){
throw InvalidCharsetException("Cyphertext contains non-alphanumeric character: "+c);
}
int q_ind = charset.indexOf(q);
if (q_ind == -1){
throw InvalidCharsetException("Password contains non-alphanumeric character: "+q); // this should NEVER happen
}
int p_int = (c_ind-q_ind)%charset_length;
char p = charset.charAt(p_int);
plaintext[i] = p;
}
return plaintext;
}
@Override @Override
public char getMapInfo() { public char getMapInfo() {
return MAP_INFO; return MAP_INFO;
@ -99,4 +171,5 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
public BasicDBObject mongoSerialise() { public BasicDBObject mongoSerialise() {
return null; return null;
} }
} }

View File

@ -84,3 +84,7 @@ wg_maxCopperCount=2
# ---------------------------------------------- # ----------------------------------------------
# Maximum execution time of user code in ms # Maximum execution time of user code in ms
user_timeout=100 user_timeout=100
# ----------------------------------------------
vault_door_open_time=4