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.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;
}
}

View File

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