package com.gdh.main; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import org.apache.log4j.Appender; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.core.json.JsonObject; /** * * * Configuration is the object which holds all the configurable parameters of a * GDHVertex. Implements the Builder pattern. * * Diffie-Hellman requires a safe prime and a cyclic group generator, both * publicly known to everyone. * * The Configuration object has these two numbers built-in, taken from * https://tools.ietf.org/html/rfc5114. * * Note these numbers must fulfill several rules in order to be safe. If you are * not using the default numbers take extreme care when choosing new ones', as your key exchange might be * vulnerable to all kinds of attacks. * * @author Max Amelchenko */ public class Configuration { private String IP = "localhost"; private String port = "1090"; private int retries = Constants.DEFAULT_RETRY; private int exchangeTimeoutMillis = Constants.EXCHANGE_TIMEOUT; private String prime = "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1B54B1597B61D0A75E6FA141DF95A56DBAF9A3C" + "407BA1DF15EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC2129037C9EDEFDA4DF8D91E8FEF55B7" + "394B7AD5B7D0B6C12207C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708B3BF8A317091883681" + "286130BC8985DB1602E714415D9330278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486DCDF93ACC" + "44328387315D75E198C641A480CD86A1B9E587E8BE60E69CC928B2B9C52172E413042E9B23F10B0E16E797" + "63C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71CF9DE5384E71B81C0AC4DFFE0C10E64F"; private String generator = "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF74866A08CFE4FFE3A6824A4E10B9A6F0DD" + "921F01A70C4AFAAB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7C17669101999024AF4D02727" + "5AC1348BB8A762D0521BC98AE247150422EA1ED409939D54DA7460CDB5F6C6B250717CBEF180EB34118E98" + "D119529A45D6F834566E3025E316A330EFBB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB10E1" + "83EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381B539CCE3409D13CD566AFBB48D6C019181E1BCFE94" + "B30269EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC017981BC087F2A7065B384B890D3191F2BFA"; private final Logger log4jLogger; public Configuration() { SecureRandom random = new SecureRandom(); this.log4jLogger = Logger.getLogger("Logger"+ random.nextInt()); ConsoleAppender appender = new ConsoleAppender(); appender.setWriter(new PrintWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8))); appender.setLayout(new PatternLayout(PatternLayout.DEFAULT_CONVERSION_PATTERN)); this.log4jLogger.addAppender(appender); this.log4jLogger.setLevel(Level.OFF); } /** * * @param IP * the ip the GDHVertex will be listening on * @return the updated configuration */ public Configuration setIP(String IP) { assert (IP.matches("(([0-1]?[0-9]{1,2}\\.)|" + "(2[0-4][0-9]\\.)|" + "(25[0-5]\\.)){3}(([0-1]?[0-9]{1,2})|" + "(2[0-4][0-9])|(25[0-5]))") || IP.contains("localhost")); this.IP = IP; return this; } /** * * @param port * the port the GDHVertex will be listening on * @return the updated configuration */ public Configuration setPort(String port) { assert port.matches("[1-9]\\d*"); this.port = port; return this; } /** * * @param retries * the number of times a GDHVertex will attempt to send a message * if delivery fails. In case the number of retries is reached * without an ack received, the key exchange is aborted. * @return the updated configuration */ public Configuration setRetries(int retries) { this.retries = retries; return this; } /** * * @param exchangeTimeoutMillis * the time limit of the Diffie-Hellman key exchange. * If the exchange takes longer than that an exception is thrown. * @return the updated configuration */ public Configuration setExchangeTimeoutMillis(int exchangeTimeoutMillis) { this.exchangeTimeoutMillis = exchangeTimeoutMillis; return this; } /** * @param generator * the cyclic group generator of this Configuration. * Needs to be large enough (2048 bits is considered safe) * @return the updated configuration */ public Configuration setGenerator(String generator) { assert generator.matches("[0-9A-F]*"); this.generator = generator; return this; } /** * @param prime * the prime number of this Configuration * Needs to be large enough (2048 bits is considered safe) * @return the updated configuration */ public Configuration setPrime(String prime) { assert prime.matches("[0-9A-F]*"); this.prime = prime; return this; } /** * * @param level * the log level to set. Default value is OFF. * @return the updated configuration */ public Configuration setLogLevel(Level level) { this.log4jLogger.setLevel(level); return this; } public String getIP() { return IP; } public String getPort() { return port; } public int getRetries() { return retries; } public Node getNode() { return new Node(IP, port); } public String getPrime() { return prime; } public String getGenerator() { return generator; } public Logger getLogger() { return log4jLogger; } public int getExchangeTimeoutMillis() { return exchangeTimeoutMillis; } /** * Setting the appender of the logger. Only one appender at a time is * allowed. * * @param app * the Appender to be set * * @return the updated configuration */ public Configuration setAppender(Appender app) { log4jLogger.removeAllAppenders(); log4jLogger.addAppender(app); return this; } /** * * @param path * the path to the configuration file * @return the Configuration object read from the file */ public static Configuration readConfigFile(String path) { Configuration conf = new Configuration(); Vertx vertx = Vertx.vertx(); vertx.fileSystem().readFile(path, res -> { Buffer buf = res.result(); JsonObject json = new JsonObject(buf); String IP = json.getString(Constants.IP); String port = json.getString(Constants.PORT); String generator = json.getString(Constants.GENERATOR); String prime = json.getString(Constants.PRIME); int retries = json.getInteger(Constants.RETRIES); conf.setIP(IP).setPort(port).setGenerator(generator).setPrime(prime).setRetries(retries); }); return conf; } @Override public int hashCode() { final int primal = 31; int result = 1; result = primal * result + ((IP == null) ? 0 : IP.hashCode()); result = primal * result + ((generator == null) ? 0 : generator.hashCode()); result = primal * result + ((port == null) ? 0 : port.hashCode()); result = primal * result + ((this.prime == null) ? 0 : this.prime.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Configuration other = (Configuration) obj; if (IP == null) { if (other.IP != null) return false; } else if (!IP.equals(other.IP)) return false; if (generator == null) { if (other.generator != null) return false; } else if (!generator.equals(other.generator)) return false; if (port == null) { if (other.port != null) return false; } else if (!port.equals(other.port)) return false; if (prime == null) { if (other.prime != null) return false; } else if (!prime.equals(other.prime)) return false; return true; } }