-
Notifications
You must be signed in to change notification settings - Fork 0
Custom Encryption
In this example, i want to show you how you can implement your own encryption mechanism into NetCom2. This is mostly nead, if you do not want to include SSL (TSL).
For this example, i want to implement the Caesar Cipher, the code of which was taken from here. This has been slightly altered, to ignore special chars and raw numbers from encryption.
Let's provide a static class for encryption and decryption and call it: Cipher
package com.github.thorbenkuck.netcom2.integration.enryption;
public class Cipher {
public static char cipher(char c, int k) {
if(!Character.isAlphabetic(c) || ! Character.isDigit(c)) {
return c;
}
// declare some helping constants
final int alphaLength = 26;
final char asciiShift = Character.isUpperCase(c) ? 'A' : 'a';
final int cipherShift = k % alphaLength;
// shift down to 0..25 for a..z
char shifted = (char) (c - asciiShift);
// rotate the letter and handle "wrap-around" for negatives and value >= 26
shifted = (char) ((shifted + cipherShift + alphaLength) % alphaLength);
// shift back up to english characters
return (char) (shifted + asciiShift);
}
public static String caesarEncryption(String string, int shift) {
if(shift < 0 || shift > 25) {
throw new IllegalArgumentException("Shift between 0 and 25 expected!");
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
sb.append(cipher(string.charAt(i), shift));
}
return sb.toString();
}
public static String caesarDecryption(String string, int shift) {
if(shift < 0 || shift > 25) {
throw new IllegalArgumentException("Shift between 0 and 25 expected!");
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
sb.append(cipher(string.charAt(i), -shift));
}
return sb.toString();
}
}This might look a bit scarry. But it is not. All we do, is that we shift any real alphabetic characters. Read the Wikipedia article and it should be clear.
As allways, we have our trusted TestObject:
import java.io.Serializable;
public class TestObject implements Serializable {
private String hello;
public TestObject(String hello) {
this.hello = hello;
}
public String getHello() {
return hello;
}
public String toString() {
return "TestObject{hello=" + hello + "}";
}
}Now, we want a Client and a Server. This will look pretty similiar to the other basic examples, the only different is, that we provide an Encryption and an Decryption Adapter for the ClientStart and the ServerStart. Lets start with the Server:
import com.github.thorbenkuck.netcom2.exceptions.ClientConnectionFailedException;
import com.github.thorbenkuck.netcom2.exceptions.StartFailedException;
import com.github.thorbenkuck.netcom2.network.server.ServerStart;
import com.github.thorbenkuck.netcom2.network.shared.clients.ObjectHandler;
public class EncryptionServer {
private final ServerStart serverStart;
public EncryptionServer(int port) {
this.serverStart = ServerStart.at(port);
}
public static void main(String[] args) {
EncryptionServer server = new EncryptionServer(4444);
try {
server.run();
} catch (StartFailedException e) {
e.printStackTrace();
}
}
public void run() throws StartFailedException {
serverStart.addClientConnectedHandler(client -> {
ObjectHandler handler = client.objectHandler();
handler.addEncryptionAdapter(string -> Cipher.caesarEncryption(string, 12));
handler.addDecryptionAdapter(string -> Cipher.caesarDecryption(string, 12));
});
serverStart.getCommunicationRegistration()
.register(TestObject.class)
.addFirst(o -> System.out.println(o.getContent()));
serverStart.launch();
try {
serverStart.acceptAllNextClients();
} catch (ClientConnectionFailedException e) {
e.printStackTrace();
}
}
}Here, we provide a clientConnectedHandler to the ServerStart. Inside this ClientConnectedHandler, we set the EncryptionAdapter and the DecryptionAdapter. Inside of those, we call the Cipher class and use the caesarEncryption/caesarDecryption with a shift of 12.
The rest is pretty much the same as the other basic examples.
The EncryptionAdapter will be called right after the Object was serialized. And the DecryptionAdapter will be called right before the String is deSerialized. This means, your EncryptionAdapter takes the Serialized Object and provides the String that will be send over the Network. And your DecryptionAdapter will take this String, that was received, right before it will be deSerialized.
Lets get back on track and create the Client. For the Client it is important that we use the same shift as at the Server-Side! Here, we simply hard-code it. This is infact a very bad idea, but we just create an Example, so lets roll with it.
import com.github.thorbenkuck.netcom2.exceptions.StartFailedException;
import com.github.thorbenkuck.netcom2.integration.TestObject;
import com.github.thorbenkuck.netcom2.network.client.ClientStart;
import com.github.thorbenkuck.netcom2.network.client.Sender;
import com.github.thorbenkuck.netcom2.network.shared.clients.ObjectHandler;
public class EncryptionClient {
private final ClientStart clientStart;
public static void main(String[] args) {
EncryptionClient client = new EncryptionClient("localhost", 4444);
try {
client.run();
} catch (StartFailedException e) {
e.printStackTrace();
}
}
public EncryptionClient(String address, int port) {
this.clientStart = ClientStart.at(address, port);
}
public void run() throws StartFailedException {
clientStart.addEncryptionAdapter(string -> Cipher.caesarEncryption(string, 12));
clientStart.addDecryptionAdapter(string -> Cipher.caesarDecryption(string, 12));
clientStart.launch();
Sender sender = Sender.open(clientStart);
while(true) {
sender.objectToServer(new TestObject("Hi!"));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}In this example we do the same as in the Server example. We provide an EncryptionAdapter and an DecryptionAdapter. The second Thing we do is, that we send every half Second to the Server. This is just done, so that this Client keeps sending and we see something the whole Time.
If you start the Server and then the Client, you will see an Output at the ServerSide.
"Hi!"
will be printed every half a Second.
Now, for having a great encryption you would need much more, like a public and a private key, you would need to interchange those key so on and so forth, but this example should get you started.
Introduction
Advanced
Outdated
Further Reading
Versions explained
Examples