How to resolve the algorithm Vigenère cipher step by step in the Java programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Vigenère cipher step by step in the Java programming language

Table of Contents

Problem Statement

Implement a   Vigenère cypher,   both encryption and decryption. The program should handle keys and text of unequal length, and should capitalize everything and discard non-alphabetic characters. (If your program handles non-alphabetic characters in another way, make a note of it.)

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Vigenère cipher step by step in the Java programming language

The Vigenere cipher is a method of encrypting alphabetic text by using a series of interwoven Caesar ciphers based on the letters of a given keyword. It is a simple but effective method of encryption that can be broken with some effort.

The provided Java code implements the Vigenere cipher using two different approaches. The first approach (in the VigenereCipher class) is a straightforward implementation that iterates over the characters of the plaintext and the key, performing the encryption/decryption operation for each character.

The second approach (in the VigenereCipher class) is a more concise and efficient implementation that uses Java 8 streams and lambda expressions. It utilizes the Stream.iterate() method to generate a stream of characters from the key, and then uses Streams.zip() to combine the plaintext stream with the key stream. The resulting stream is then mapped to the encrypted/decrypted characters, and the final result is collected into a string.

The VigenereCipherTest class contains a unit test that demonstrates the functionality of the cipher by encrypting and decrypting a plaintext string and asserting that the decrypted string matches the original plaintext.

Here's a detailed explanation of the Java code:

  • The first VigenereCipher class implements the Vigenere cipher using a straightforward approach. It has two static methods: encrypt() and decrypt().

    • The encrypt() method takes a plaintext string and a key string as input, and returns an encrypted string. It iterates over the characters of the plaintext and the key, and for each character, it performs the encryption operation by adding the ASCII code of the plaintext character and the ASCII code of the key character, and then taking the result modulo 26 (to wrap around the alphabet).

    • The decrypt() method takes an encrypted string and a key string as input, and returns a decrypted string. It iterates over the characters of the encrypted string and the key, and for each character, it performs the decryption operation by subtracting the ASCII code of the key character from the ASCII code of the encrypted character, and then taking the result modulo 26 (to wrap around the alphabet).

  • The second VigenereCipher class implements the Vigenere cipher using a more concise and efficient approach. It has a constructor that takes a key string as input, and two methods: encrypt() and decrypt().

    • The encrypt() method takes a plaintext string as input, and returns an encrypted string. It uses Java 8 streams and lambda expressions to perform the encryption operation. It first converts the plaintext string to uppercase, and then uses Stream.iterate() to generate a stream of characters from the key. The plaintext stream and the key stream are then combined using Streams.zip(), and the resulting stream is mapped to the encrypted characters. The final result is collected into a string.

    • The decrypt() method takes an encrypted string as input, and returns a decrypted string. It uses Java 8 streams and lambda expressions to perform the decryption operation. It first converts the encrypted string to uppercase, and then uses Stream.iterate() to generate a stream of characters from the key. The encrypted stream and the key stream are then combined using Streams.zip(), and the resulting stream is mapped to the decrypted characters. The final result is collected into a string.

  • The VigenereCipherTest class contains a unit test that demonstrates the functionality of the cipher. It creates an instance of the VigenereCipher class with a key string, and then encrypts and decrypts a plaintext string. The decrypted string is then compared to the original plaintext, and the test passes if they match.

Source code in the java programming language

public class VigenereCipher {
    public static void main(String[] args) {
        String key = "VIGENERECIPHER";
        String ori = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!";
        String enc = encrypt(ori, key);
        System.out.println(enc);
        System.out.println(decrypt(enc, key));
    }

    static String encrypt(String text, final String key) {
        String res = "";
        text = text.toUpperCase();
        for (int i = 0, j = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            if (c < 'A' || c > 'Z') continue;
            res += (char)((c + key.charAt(j) - 2 * 'A') % 26 + 'A');
            j = ++j % key.length();
        }
        return res;
    }

    static String decrypt(String text, final String key) {
        String res = "";
        text = text.toUpperCase();
        for (int i = 0, j = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            if (c < 'A' || c > 'Z') continue;
            res += (char)((c - key.charAt(j) + 26) % 26 + 'A');
            j = ++j % key.length();
        }
        return res;
    }
}


import com.google.common.collect.Streams;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.nio.charset.StandardCharsets.US_ASCII;

public class VigenereCipher {
    private final static int LOWER = 'A';
    private final static int UPPER = 'Z';
    private final static int SIZE = UPPER - LOWER + 1;
    private final Supplier<Stream<Character>> maskStream;

    public VigenereCipher(final String key) {
        final String mask = new String(key.getBytes(US_ASCII)).toUpperCase();
        maskStream = () ->
                Stream.iterate(0, i -> (i+1) % mask.length()).map(mask::charAt);
    }

    private String transform(final String text, final boolean encode) {
        final Stream<Integer> textStream = text.toUpperCase().chars().boxed()
                .filter(i -> i >= LOWER && i <= UPPER);
        return Streams.zip(textStream, maskStream.get(), (c, m) ->
                encode ? c + m - 2 * LOWER : c - m + SIZE)
            .map(c -> Character.toString(c % SIZE + LOWER))
            .collect(Collectors.joining());
    }

    public String encrypt(final String plaintext) {
        return transform(plaintext,true);
    }

    public String decrypt(final String ciphertext) {
        return transform(ciphertext,false);
    }
}

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class VigenereCipherTest {
    private static final VigenereCipher Vigenere = new VigenereCipher("VIGENERECIPHER");

    @Test
    @DisplayName("encipher/decipher round-trip succeeds")
    void vigenereCipherTest() {
        final String input = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!";
        final String expectEncrypted = "WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY";
        final String expectDecrypted = "BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH";

        final String ciphertext = Vigenere.encrypt(input);
        assertEquals(expectEncrypted, ciphertext);

        final String plaintext = Vigenere.decrypt(ciphertext);
        assertEquals(expectDecrypted, plaintext);
    }

}


  

You may also check:How to resolve the algorithm Nested function step by step in the Elena programming language
You may also check:How to resolve the algorithm Sum of a series step by step in the Action! programming language
You may also check:How to resolve the algorithm Semordnilap step by step in the M2000 Interpreter programming language
You may also check:How to resolve the algorithm String length step by step in the Pop11 programming language
You may also check:How to resolve the algorithm Van Eck sequence step by step in the APL programming language