RSA Encrypt/Decrypt Ciphers for Client-Server Application : Android | Spring

Client-Server RSA Encrytion/Decryption

This is part 2 of the Java RSA Encryption Series, PART 1 HERE.

Before starting, we will modify the previously written code by moving the content of the constructor in an init() method and removing the construction. The result will be :

public void init(){
    try {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(1024);
        KeyPair pair = generator.generateKeyPair();
        privateKey = pair.getPrivate();
        publicKey = pair.getPublic();
    } catch (Exception ignored) {
    }
}

The main will also change to

public static void main(String[] args) {
    RSA rsa = new RSA();
    rsa.init();
    try{
        String encryptedMessage = rsa.encrypt("Hello World");
        String decryptedMessage = rsa.decrypt(encryptedMessage);

        System.err.println("Encrypted:\n"+encryptedMessage);
        System.err.println("Decrypted:\n"+decryptedMessage);

    }catch (Exception ingored){}
}

Now let’s add a method to print out the private and public keys and for that, we will need the encode() method we have previously created.

public void printKeys(){
        System.err.println("Public key\n"+ encode(publicKey.getEncoded()));
        System.err.println("Private key\n"+ encode(privateKey.getEncoded()));
}

The method can be added to the main method after the init() call.

Now that we can see the encoded keys, we can copy them and place them in final variables like so :

private static final String PRIVATE_KEY_STRING = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhBgzcXBm5A0srvFFu4FsBy+LLW+X0sH/9RvP40VIGOCusY0/CqA65YXWqyQE5jQCegBmnAeVYSvK+3PU4Y1fmr1uiquE6sZB5sl96T0ka+PKzPf4oKoAi6nwLUSenj5xTFjLsFGiuMXrCpMCPImf9JBVk89TJV43Xs3DSNKoj1AgMBAAECgYBsDysCgVv2ChnRH4eSZP/4zGCIBR0C4rs+6RM6U4eaf2ZuXqulBfUg2uRKIoKTX8ubk+6ZRZqYJSo3h9SBxgyuUrTehhOqmkMDo/oa9v7aUqAKw/uoaZKHlj+3p4L3EK0ZBpz8jjs/PXJc77Lk9ZKOUY+T0AW2Fz4syMaQOiETzQJBANF5q1lntAXN2TUWkzgir+H66HyyOpMu4meaSiktU8HWmKHa0tSB/v7LTfctnMjAbrcXywmb4ddixOgJLlAjEncCQQC6Enf3gfhEEgZTEz7WG9ev/M6hym4C+FhYKbDwk+PVLMVR7sBAtfPkiHVTVAqC082E1buZMzSKWHKAQzFL7o7zAkBye0VLOmLnnSWtXuYcktB+92qh46IhmEkCCA+py2zwDgEiy/3XSCh9Rc0ZXqNGD+0yQV2kpb3awc8NZR8bit9nAkBo4TgVnoCdfbtq4BIvBQqR++FMeJmBuxGwv+8n63QkGFQwVm6vCuAqFHBtQ5WZIGFbWk2fkKkwwaHogfcrYY/ZAkEAm5ibtJx/jZdPEF9VknswFTDJl9xjIfbwtUb6GDMc0KH7v+QTBW4GsHwt/gL+kGvLOLcEdLL5rau3IC7EQT0ZYg==";

private static final String PUBLIC_KEY_STRING =  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYQYM3FwZuQNLK7xRbuBbAcviy1vl9LB//Ubz+NFSBjgrrGNPwqgOuWF1qskBOY0AnoAZpwHlWEryvtz1OGNX5q9boqrhOrGQebJfek9JGvjysz3+KCqAIup8C1Enp4+cUxYy7BRorjF6wqTAjyJn/SQVZPPUyVeN17Nw0jSqI9QIDAQAB";

Now let’s create a method initFromStrings() that will generate the key pair from these strings. But since the public key and the private key are different, we will need different encoders.

For the Public key, we will use X509EncodedKeySpec and for the private key, we will use PKCS8EncodedKeySpec

public void initFromStrings(){
    try{
        X509EncodedKeySpec keySpecPublic = new X509EncodedKeySpec(decode(PUBLIC_KEY_STRING));
        PKCS8EncodedKeySpec keySpecPrivate = new PKCS8EncodedKeySpec(decode(PRIVATE_KEY_STRING));

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        publicKey = keyFactory.generatePublic(keySpecPublic);
        privateKey = keyFactory.generatePrivate(keySpecPrivate);
    }catch (Exception ignored){}
}

Now we only need to change the main method to

public static void main(String[] args) {
    RSA rsa = new RSA();
    rsa.initFromStrings();
    try{
        String encryptedMessage = rsa.encrypt("Hello World");
        String decryptedMessage = rsa.decrypt(encryptedMessage);

        System.err.println("Encrypted:\n"+encryptedMessage);
        System.err.println("Decrypted:\n"+decryptedMessage);

    }catch (Exception ingored){}
}

Here is the full code


Creating a client sever Application

To make this application a client that will decrypt the messages received from a server, we can remove the methods that we don’t need, like the encrypt(), and few other lines.

We will also add the artifact okhttp3 if you are using a Maven project add this to pom.xml

<dependency>
    <groupId>com.squareup.okhttp</groupId>
    <artifactId>okhttp</artifactId>
    <version>2.7.5</version>
</dependency>

For Gradle use

implementation group: 'com.squareup.okhttp', name: 'okhttp', version: '2.7.5'

We will change the body of the main() method to

public static void main(String[] args) {
    RSA rsa = new RSA();
    rsa.initFromStrings();

    try{
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://localhost:3000/getSecretMessage")
                .method("GET",null)
                .build();

        Response response = client.newCall(request).execute();
        String encryptedMessage = response.body().string();
        System.err.println("RESPONSE BODY = "+encryptedMessage);

        String secretMessage = rsa.decrypt(encryptedMessage);
        System.err.println("SECRET MESSAGE = "+secretMessage);

    }catch (Exception ignored){}

}

And we are good to go! The result is:

RESPONSE BODY = KeEYSClfaJWi9ez4aN9LKfwrz9gySqx1qW7UO89/kGK+0ryeK+fO70pdE/g6qm9QcJxwenHb3dilesYOWTFxf6Bpss5U5FLaTlI5QoKBqvxrCesC7UU0SyI5CqJT0ytiK1DDiu/QCiuw0Sh0YaiXBDrc2wVPfPy4NqH4t4JcE9o=
SECRET MESSAGE = TheXCoders

Full Client code:

Full sever Code (Spring)

For the application.properties I have changed the port to 3000 (I have another application running on port 8080)

server.port=3000