From 46483b2bf81d7c1acc43bac99e3fe1f91ae2c59c Mon Sep 17 00:00:00 2001 From: sg495 Date: Mon, 8 Jan 2018 20:40:50 +0100 Subject: [PATCH] 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. --- .../vaultplugin/InvalidCharsetException.java | 16 ++ .../simon987/vaultplugin/RandomString.java | 68 +++++++++ .../net/simon987/vaultplugin/VaultDoor.java | 137 ++++++++++++++---- Server/src/main/resources/config.properties | 4 + 4 files changed, 193 insertions(+), 32 deletions(-) create mode 100644 Plugin Vault/src/main/java/net/simon987/vaultplugin/InvalidCharsetException.java create mode 100644 Plugin Vault/src/main/java/net/simon987/vaultplugin/RandomString.java diff --git a/Plugin Vault/src/main/java/net/simon987/vaultplugin/InvalidCharsetException.java b/Plugin Vault/src/main/java/net/simon987/vaultplugin/InvalidCharsetException.java new file mode 100644 index 0000000..8894b49 --- /dev/null +++ b/Plugin Vault/src/main/java/net/simon987/vaultplugin/InvalidCharsetException.java @@ -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); + } \ No newline at end of file diff --git a/Plugin Vault/src/main/java/net/simon987/vaultplugin/RandomString.java b/Plugin Vault/src/main/java/net/simon987/vaultplugin/RandomString.java new file mode 100644 index 0000000..791e21c --- /dev/null +++ b/Plugin Vault/src/main/java/net/simon987/vaultplugin/RandomString.java @@ -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); + } + +} \ No newline at end of file diff --git a/Plugin Vault/src/main/java/net/simon987/vaultplugin/VaultDoor.java b/Plugin Vault/src/main/java/net/simon987/vaultplugin/VaultDoor.java index 5103a8a..ab900d4 100644 --- a/Plugin Vault/src/main/java/net/simon987/vaultplugin/VaultDoor.java +++ b/Plugin Vault/src/main/java/net/simon987/vaultplugin/VaultDoor.java @@ -6,6 +6,7 @@ import net.simon987.server.game.GameObject; import net.simon987.server.game.Programmable; import net.simon987.server.game.Updatable; import net.simon987.server.logging.LogManager; +import net.simon987.vaultplugin.RandomString; import java.util.Arrays; @@ -19,31 +20,45 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up */ private char[] password; + private RandomString random_string_generator; + /** * 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 */ - 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 public void update() { - - if (openedTimer <= 0) { - - //Door was opened for OPEN_TIME, close it and regen password - password = getRandomPassword(); - opened = false; - - LogManager.LOGGER.fine("Closed Vault door ID: " + getObjectId()); - } else { - openedTimer--; + if (open){ + if (openedTimer <= 0) { + //Door was open for OPEN_TIME, close it and regen password + password = getRandomPassword(); + open = false; + openedTimer = 0; + LogManager.LOGGER.fine("Closed Vault door ID: " + getObjectId()); + } + else{ + openedTimer--; + } } } @@ -51,45 +66,102 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up @Override public boolean sendMessage(char[] message) { - System.out.println("VAULT: sendMessage" + new String(message));//todo rmv - - if (!opened) { - - if (Arrays.equals(message, password)) { - opened = true; - openedTimer = OPEN_TIME; - - LogManager.LOGGER.fine("Opened Vault door ID: " + getObjectId()); + if (Arrays.equals(message, password)) { + if (!open) { + openVault(); + } + else{ + keepVaultOpen(); } - return true; - } else { - //Can't receive messages when opened + } + else { return false; } } + private void openVault(){ + open = true; + openedTimer = OPEN_TIME; + LogManager.LOGGER.fine("Opened Vault door ID: " + getObjectId()); + } + + private void keepVaultOpen(){ + open = true; + openedTimer = OPEN_TIME; + } + @Override public boolean enter(GameObject object) { - LogManager.LOGGER.fine("VAULT enter " + opened); - - if (opened) { + LogManager.LOGGER.fine("VAULT enter " + open); + if (open) { //TODO: Enter in the vault - - return true; } else { return false; } - } + /** + * Generates a random alphanumeric string using the RandomString class + */ 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 public char getMapInfo() { return MAP_INFO; @@ -99,4 +171,5 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up public BasicDBObject mongoSerialise() { return null; } + } diff --git a/Server/src/main/resources/config.properties b/Server/src/main/resources/config.properties index 1c925dc..4647df3 100644 --- a/Server/src/main/resources/config.properties +++ b/Server/src/main/resources/config.properties @@ -84,3 +84,7 @@ wg_maxCopperCount=2 # ---------------------------------------------- # Maximum execution time of user code in ms user_timeout=100 + + +# ---------------------------------------------- +vault_door_open_time=4 \ No newline at end of file