+1 (315) 557-6473 

Program To Adjust Your Implementation of The Substitution in Java Assignment Solution.


Instructions

Objective
Write a java assignment program to adjust your implementation of the substitution.

Requirements and Specifications

Description of activity: In this exercise I would like you to adjust your implementation of the substitution (also known as mono-alphabetic) cipher.
Vigenere (also known as poly-alphabetic) cipher attempts to “smoothen out” the plaintext->ciphertext letter frequencies which occur in light of the one-to-one plaintext->ciphertext pairing embodied in the shift cipher.
Vigenere is explained in detail in the version 2 of the book on page 13. Your scheme should still implement all 3 algorithms namely key-generation, encryption, decryption. Ultimately you will use this programming exercise to play a mental game with yourself, where you play part of the sender (Alice), recipient (Bob) and malicious attacker (Eve). The outcome of this exercise is to see for yourself how the letter frequency cryptanalysis of the substitution cipher can be easily corrected via a poly-alphabetic method. Vigenere cipher is not a secure cipher, however in this exercise you do not need to worry and crypto analyse it, all you have to do is show me how the cryptanalysis of Substitution cipher is no longer possible here in the Vigenere cipher.
Source Code
FREQUENCY ATTACKER
import java.io.File;
import java.io.IOException;
import java.util.*;
public class FrequencyAttack {
    private static final char CHARS_BY_FREQUENCIES[] = {'e', 't', 'a', 'o', 'i', 'n', 's', 'r', 'h', 'l',
            'd', 'c', 'u', 'm', 'f', 'p', 'g', 'w', 'y', 'b',
            'v', 'k', 'x', 'j', 'q', 'z'};
    private SubstitutionCipher attackingCipher;
    private Map counters;
    public FrequencyAttack() {
        counters = new HashMap<>();
        Character[] plainText = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
                'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                'u', 'v', 'w', 'x', 'y', 'z'};
        for (Character c : plainText) {
            counters.put(c, 0);
        }
    }
    public void addCorpus(String encryptedCorpus) {
        for (int i = 0; i
            char c = encryptedCorpus.charAt(i);
            if (c >= 'a' && c <= 'z') {
                counters.merge(c, 1, Integer::sum);
            }
        }
    }
    public String attack(String fragment) {
        Character[] plainText = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
                'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                'u', 'v', 'w', 'x', 'y', 'z'};
        Arrays.sort(plainText, (o1, o2) -> Integer.compare(counters.get(o2), counters.get(o1)));
        char[] chars = new char[plainText.length];
        for (int i = 0; i < plainText.length; i++) {
            chars[i] = plainText[i];
        }
        attackingCipher = new SubstitutionCipher(CHARS_BY_FREQUENCIES, chars);
        System.out.println("Attacking key, based on frequencies: ");
        attackingCipher.printKey();
        System.out.println();
        return attackingCipher.decrypt(fragment);
    }
    public static void main(String[] args) {
        VigenereCipher cipher = new VigenereCipher("cafe");
        FrequencyAttack frequencyAttack = new FrequencyAttack();
        // creating encrypted corpus of text
        System.out.println("Loading and encrypting corpus of text...");
        String encryptedCorpus = getEncryptedCorpus("text.txt", cipher);
        frequencyAttack.addCorpus(encryptedCorpus);
        String fragment = "veqpjiredozxoe";
        System.out.println("Trying to make attack on encrypted code fragment: " + fragment);
        System.out.println("The result of the attack: " + frequencyAttack.attack(fragment));
    }
    private static String getEncryptedCorpus(String filename, VigenereCipher cipher) {
        try (Scanner scanner = new Scanner(new File(filename))) {
            StringBuilder builder = new StringBuilder();
            while(scanner.hasNextLine()) {
                builder.append(scanner.nextLine().trim().toLowerCase());
            }
            return cipher.encrypt(builder.toString());
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
SUBSTITUTION CIPHER
import java.text.MessageFormat;
import java.util.*;
public class SubstitutionCipher {
    private Map key;
    public SubstitutionCipher() {
        generateKey();
    }
    public SubstitutionCipher(char[] letters, char[] substitutions) {
        int size = 'z' - 'a' + 1;
        // populating result map
        key = new HashMap<>();
        for (int i = 0; i
            key.put(letters[i], substitutions[i]);
        }
    }
    public String encrypt(String s) {
        String lowercase = s.toLowerCase();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < lowercase.length(); i++) {
            char c = lowercase.charAt(i);
            if (key.containsKey(c)) {
                builder.append(key.get(c));
            }
            else {
                builder.append(c);
            }
        }
        return builder.toString();
    }
    public String decrypt(String s) {
        String lowercase = s.toLowerCase();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < lowercase.length(); i++) {
            char c = lowercase.charAt(i);
            Character decryptedC = key.entrySet().stream()
                    .filter(pair -> pair.getValue().equals(c))
                    .map(Map.Entry::getKey).findAny().orElse(null);
            if (decryptedC != null) {
                builder.append(decryptedC);
            }
            else {
                builder.append(c);
            }
        }
        return builder.toString();
    }
    public void printKey() {
        List> sorted = new ArrayList<>(key.entrySet());
        sorted.sort((o1, o2) -> Character.compare(o1.getKey(), o2.getKey()));
        StringBuilder builder = new StringBuilder();
        for (Map.Entry pair : sorted) {
            builder.append(MessageFormat.format("{0} -> {1}", pair.getKey(), pair.getValue())).append(System.lineSeparator());
        }
        System.out.println(builder);
    }
    private void generateKey() {
        int size = 'z' - 'a' + 1;
        char[] letters = new char[size];
        char[] substitutions = new char[size];
        // filling arrays
        for (char c = 'a'; c <= 'z'; c++) {
            letters[c - 'a'] = c;
            substitutions[c - 'a'] = c;
        }
        // permuting substitution array
        Random random = new Random();
        for (int i = size-1; i>0; i--) {
            int index = random.nextInt(i);
            if (index != i) {
                char sw = substitutions[i];
                substitutions[i] = substitutions[index];
                substitutions[index] = sw;
            }
        }
        // populating result map
        key = new HashMap<>();
        for (int i = 0; i
            key.put(letters[i], substitutions[i]);
        }
    }
    public static void main(String[] args) {
        char[] plainText = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
                'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                'u', 'v', 'w', 'x', 'y', 'z'};
        char[] encrypted = {'b', 'e', 'c', 'd', 'f', 'g', 'h', 'z', 'j', 'k',
                'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
                'v', 'w', 'x', 'y', 'a', 'i'};
        SubstitutionCipher cipher = new SubstitutionCipher(plainText, encrypted);
        cipher.printKey();
        String text = "shesellsseashellsbytheseashore";
        System.out.println("Plain Text: " + text);
        String encryptedText = cipher.encrypt(text);
        System.out.println("Encrypted Text: " + encryptedText);
        String decryptedText = cipher.decrypt(encryptedText);
        System.out.println("Decrypted Text: " + decryptedText);
        System.out.println();
        encryptedText = "jsfbmmampwfcsaqup";
        System.out.println("Encrypted Text: " + encryptedText);
        decryptedText = cipher.decrypt(encryptedText);
        System.out.println("Decrypted Text: " + decryptedText);
        System.out.println();
    }
}
VIGENERE CIPHER
public class VigenereCipher {
    private final String keyWord;
    public VigenereCipher(String keyWord) {
        this.keyWord = keyWord.toLowerCase();
    }
    public String encrypt(String s) {
        String lowercase = s.toLowerCase();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < lowercase.length(); i++) {
            int charI = lowercase.charAt(i) - 'a';
            int keyI = keyWord.charAt(i % keyWord.length()) - 'a';
            builder.append(((char)((charI + keyI) % 26 + 'a')));
        }
        return builder.toString();
    }
    public String decrypt(String s) {
        String lowercase = s.toLowerCase();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < lowercase.length(); i++) {
            int charI = lowercase.charAt(i) - 'a';
            int keyI = keyWord.charAt(i % keyWord.length()) - 'a';
            builder.append(((char)((charI - keyI + 26) % 26 + 'a')));
        }
        return builder.toString();
    }
    public static void main(String[] args) {
        VigenereCipher cipher = new VigenereCipher("cafe");
        String text = "tellhimaboutme";
        System.out.println("Plain Text: " + text);
        String encryptedText = cipher.encrypt(text);
        System.out.println("Encrypted Text: " + encryptedText);
        String decryptedText = cipher.decrypt(encryptedText);
        System.out.println("Decrypted Text: " + decryptedText);
        System.out.println();
    }
}