Merge pull request #120 from sg495/vaults

New additional code for Vault doors
This commit is contained in:
Simon Fortier 2018-01-09 19:22:42 -05:00 committed by GitHub
commit f1c1f8f807
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 460 additions and 33 deletions

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.server.crypto.CryptoProvider;
import java.util.Arrays;
@ -19,31 +20,42 @@ 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 cypher_id;
public VaultDoor(int cypher_id){
this.cypher_id = cypher_id;
this.random_string_generator = new RandomStringGenerator(PASSWORD_LENGTH);
password = GameServer.INSTANCE.getConfig().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 = GameServer.INSTANCE.getConfig().getRandomPassword();
open = false;
openedTimer = 0;
LogManager.LOGGER.fine("Closed Vault door ID: " + getObjectId());
} else {
openedTimer--;
}
}
}
@ -51,44 +63,42 @@ 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
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;
}
}
private static char[] getRandomPassword() {
return "12345678".toCharArray();//todo actual random password
}
@Override
public char getMapInfo() {
@ -99,4 +109,5 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
public BasicDBObject mongoSerialise() {
return null;
}
}

View File

@ -14,6 +14,7 @@ import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.PluginManager;
import net.simon987.server.user.User;
import net.simon987.server.webserver.SocketServer;
import net.simon987.server.crypto.CryptoProvider;
import java.io.File;
import java.net.UnknownHostException;
@ -36,6 +37,8 @@ public class GameServer implements Runnable {
private DayNightCycle dayNightCycle;
private CryptoProvider cryptoProvider;
public GameServer() {
this.config = new ServerConfiguration("config.properties");
@ -45,6 +48,7 @@ public class GameServer implements Runnable {
maxExecutionTime = config.getInt("user_timeout");
cryptoProvider = new CryptoProvider();
dayNightCycle = new DayNightCycle();
@ -79,6 +83,10 @@ public class GameServer implements Runnable {
return eventDispatcher;
}
public CryptoProvider getCryptoProvider(){
return cryptoProvider;
}
@Override
public void run() {
LogManager.LOGGER.info("(G) Started game loop");

View File

@ -0,0 +1,31 @@
package net.simon987.server.crypto;
public class AutokeyCypher extends ShiftSubstitutionCypher {
public AutokeyCypher(String charset){
super(charset);
}
public AutokeyCypher(){
super();
}
@override
protected char encryptionShiftAt(int position, char[] plaintext, char[] key, char[] partial_cyphertext){
if (i<key.length){
return key[i];
} else {
return plaintext[i-key.length];
}
}
@override
protected char decryptionShiftAt(int position, char[] cyphertext, char[] key, char[] partial_plaintext){
if (i<key.length){
return key[i];
} else {
return partial_plaintext[i-key.length];
}
}
}

View File

@ -0,0 +1,29 @@
package net.simon987.server.crypto;
public class CaesarCypher extends ShiftSubstitutionCypher {
public CaesarCypher(String charset){
super(charset);
}
public CaesarCypher(){
super();
}
/**
* Uses the first character of the key as the shift, and ignores the rest.
*/
@override
protected char encryptionShiftAt(int position, char[] plaintext, char[] key, char[] partial_cyphertext){
return key[0];
}
/**
* Uses the first character of the key as the shift, and ignores the rest.
*/
@override
protected char decryptionShiftAt(int position, char[] cyphertext, char[] key, char[] partial_plaintext){
return key[0];
}
}

View File

@ -0,0 +1,22 @@
package net.simon987.server.crypto;
public class CryptoException extends Exception {
public CryptoException () {
}
public CryptoException (String message) {
super (message);
}
public CryptoException (Throwable cause) {
super (cause);
}
public CryptoException (String message, Throwable cause) {
super (message, cause);
}
}

View File

@ -0,0 +1,43 @@
package net.simon987.server.crypto;
public class CryptoProvider{
public static final int NO_CYPHER = 0x0000;
public static final int CAESAR_CYPHER = 0x0001;
public static final int VIGENERE_CYPHER = 0x0002;
public static final int AUTOKEY_CYPHER = 0x0003;
public static final int PASSWORD_LENGTH = 8; // Same as CubotComPort.MESSAGE_LENGTH
private charset;
private password_generator;
public CryptoProvider(String charset){
this.charset = charset;
this.password_generator = new RandomStringGenerator(PASSWORD_LENGTH,charset);
}
public CryptoProvider(){
this(RandomStringGenerator.ALPHANUMERIC_CHARSET);
}
public Cypher getCypher(int cypherId){
switch (cypherId){
case NO_CYPHER:
return new NoCypher(charset);
case CAESAR_CYPHER:
return new CaesarCypher(charset);
case VIGENERE_CYPHER:
return new VigenereCypher(charset);
case AUTOKEY_CYPHER:
return new AutokeyCypher(charset);
default:
return null;
}
}
public static String getRandomPassword(){
return this.password_generator.nextString().toCharArray();
}
}

View File

@ -0,0 +1,13 @@
package net.simon987.server.crypto;
interface Cypher {
public char[] encrypt(char[] plaintext, char[] key);
public char[] decrypt(char[] cyphertext, char[] key);
public String textCharset();
public String keyCharset();
}

View File

@ -0,0 +1,22 @@
package net.simon987.server.crypto;
public class InvalidCharsetException extends CryptoException {
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,22 @@
package net.simon987.server.crypto;
public class InvalidKeyException extends CryptoException {
public InvalidKeyException () {
}
public InvalidKeyException (String message) {
super (message);
}
public InvalidKeyException (Throwable cause) {
super (cause);
}
public InvalidKeyException (String message, Throwable cause) {
super (message, cause);
}
}

View File

@ -0,0 +1,50 @@
package net.simon987.server.crypto;
public abstract class NoCypher implements Cypher {
private String charset;
public NoCypher(String charset){
this.charset = charset;
}
public NoCypher(){
this(RandomStringGenerator.alphanum);
}
public char[] encrypt(char[] plaintext, char[] key){
char[] cyphertext = new char[plaintext.length];
for (int i = 0; i< plaintext.length; i++){
char p = plaintext[i];
int p_ind = charset.indexOf(p);
if (p_ind == -1){
throw InvalidCharsetException("Plaintext contains invalid character: "+p);
}
cyphertext[i] = p;
}
return cyphertext;
}
public char[] decrypt(char[] cyphertext, char[] key){
char[] plaintext = new char[cyphertext.length];
for (int i = 0; i< cyphertext.length; i++){
char c = cyphertext[i];
int c_ind = charset.indexOf(c);
if (c_ind == -1){
throw InvalidCharsetException("Cyphertext contains invalid character: "+c);
}
plaintext[i] = c;
}
return plaintext;
}
public String textCharset(){
return charset;
}
public String keyCharset(){
return charset;
}
}

View File

@ -0,0 +1,74 @@
/**
*
* Based on the RandomString class by erickson:
* https://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string
*
*/
package net.simon987.server.crypto;
import java.security.SecureRandom;
import java.util.Locale;
import java.util.Objects;
import java.util.Random;
public class RandomStringGenerator {
/**
* Generate a random string.
*/
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = charset[random.nextInt(charset.length)];
return new String(buf);
}
public static final String UPPER_ALPHA_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String LOWER_ALPHA_CHARSET = UPPER_ALPHA_CHARSET.toLowerCase(Locale.ROOT);
public static final String NUMERIC_CHARSET = "0123456789";
public static final String ALPHANUMERIC_CHARSET = UPPER_ALPHA_CHARSET + LOWER_ALPHA_CHARSET + NUMERIC_CHARSET;
private final Random random;
private final char[] charset;
private final char[] buf;
public RandomStringGenerator(int length, Random random, String charset) {
if (length < 1) throw new IllegalArgumentException();
if (charset.length() < 2) throw new IllegalArgumentException();
this.random = Objects.requireNonNull(random);
this.charset = charset.toCharArray();
this.buf = new char[length];
}
/**
* Create an alphanumeric string generator.
*/
public RandomStringGenerator(int length, Random random) {
this(length, random, alphanum);
}
/**
* Create an alphanumeric string generator using the given charset.
*/
public RandomStringGenerator(int length, String charset) {
this(length, new SecureRandom(), ALPHANUMERIC_CHARSET);
}
/**
* Create an alphanumeric strings from a secure generator.
*/
public RandomStringGenerator(int length) {
this(length, new SecureRandom(),ALPHANUMERIC_CHARSET);
}
/**
* Create 8-character alphanumeric strings from a secure generator.
*/
public RandomStringGenerator() {
this(8);
}
}

View File

@ -0,0 +1,73 @@
package net.simon987.server.crypto;
public abstract class ShiftSubstitutionCypher implements Cypher {
private String charset;
public ShiftSubstitutionCypher(String charset){
this.charset = charset;
}
public ShiftSubstitutionCypher(){
this(RandomStringGenerator.alphanum);
}
protected abstract char encryptionShiftAt(int position, char[] plaintext, char[] key, char[] partial_cyphertext);
protected abstract char decryptionShiftAt(int position, char[] cyphertext, char[] key, char[] partial_plaintext);
public char[] encrypt(char[] plaintext, char[] key){
if (key.length==0){
throw InvalidKeyException("Key is empty");
}
int charset_length = charset.length();
char[] cyphertext = new char[plaintext.length];
for (int i = 0; i< plaintext.length; i++){
char p = plaintext[i];
char k = encryptionShiftAt(i,plaintext,key,cyphertext);
int p_ind = charset.indexOf(p);
if (p_ind == -1){
throw InvalidCharsetException("Plaintext contains invalid character: "+p);
}
int k_ind = charset.indexOf(k);
if (k_ind == -1){
throw InvalidCharsetException("Key contains invalid character: "+k);
}
int c_int = (p_ind+k_ind)%charset_length;
char c = charset.charAt(c_int);
cyphertext[i] = c;
}
return cyphertext;
}
public char[] decrypt(char[] cyphertext, char[] key){
if (key.length==0){
throw InvalidKeyException("Key is empty");
}
int charset_length = charset.length();
char[] plaintext = new char[cyphertext.length];
for (int i = 0; i< cyphertext.length; i++){
char c = cyphertext[i];
char k = decryptionShiftAt(i,cyphertext,key,plaintext);
int c_ind = charset.indexOf(c);
if (c_ind == -1){
throw InvalidCharsetException("Cyphertext contains invalid character: "+c);
}
int k_ind = charset.indexOf(k);
if (k_ind == -1){
throw InvalidCharsetException("Password contains invalid character: "+k);
}
int p_int = (c_ind-k_ind)%charset_length;
char p = charset.charAt(p_int);
plaintext[i] = p;
}
return plaintext;
}
public String textCharset(){
return charset;
}
public String keyCharset(){
return charset;
}
}

View File

@ -0,0 +1,25 @@
package net.simon987.server.crypto;
public class VigenereCypher extends ShiftSubstitutionCypher {
public VigenereCypher(String charset){
super(charset);
}
public VigenereCypher(){
super();
}
@override
protected char encryptionShiftAt(int position, char[] plaintext, char[] key, char[] partial_cyphertext){
int j = i % key.length;
return key[j];
}
@override
protected char decryptionShiftAt(int position, char[] cyphertext, char[] key, char[] partial_plaintext){
int j = i % key.length;
return key[j];
}
}

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