Untitled

 avatar
unknown
plain_text
5 days ago
5.3 kB
0
Indexable
import java.util.Scanner;

public class HillCipher {
    
    static int[][] keyMatrix;
    static int matrixSize;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter the matrix size (n x n): ");
        matrixSize = scanner.nextInt();

        keyMatrix = new int[matrixSize][matrixSize];

        System.out.println("Enter the key matrix:");
        for (int i = 0; i < matrixSize; i++) {
            for (int j = 0; j < matrixSize; j++) {
                keyMatrix[i][j] = scanner.nextInt();
            }
        }

        System.out.print("Enter the plaintext (uppercase only): ");
        scanner.nextLine();
        String plaintext = scanner.nextLine();
        plaintext = prepareText(plaintext, matrixSize);

        String ciphertext = encrypt(plaintext);
        System.out.println("Encrypted Text: " + ciphertext);

        String decryptedText = decrypt(ciphertext);
        System.out.println("Decrypted Text: " + decryptedText);

        scanner.close();
    }

    private static String encrypt(String text) {
        int[] textVector = textToNumbers(text);
        int[] encryptedVector = matrixMultiply(keyMatrix, textVector);
        return numbersToText(encryptedVector);
    }

    private static String decrypt(String ciphertext) {
        int[][] inverseMatrix = findModularInverse(keyMatrix, 26);
        if (inverseMatrix == null) {
            return "Decryption not possible (key matrix is not invertible mod 26)";
        }
        int[] cipherVector = textToNumbers(ciphertext);
        int[] decryptedVector = matrixMultiply(inverseMatrix, cipherVector);
        return numbersToText(decryptedVector);
    }

    private static int[] textToNumbers(String text) {
        int[] numbers = new int[text.length()];
        for (int i = 0; i < text.length(); i++) {
            numbers[i] = text.charAt(i) - 'A';
        }
        return numbers;
    }

    private static String numbersToText(int[] numbers) {
        StringBuilder text = new StringBuilder();
        for (int num : numbers) {
            text.append((char) ((num % 26 + 26) % 26 + 'A'));
        }
        return text.toString();
    }

    private static int[] matrixMultiply(int[][] matrix, int[] vector) {
        int[] result = new int[vector.length];
        for (int i = 0; i < matrix.length; i++) {
            int sum = 0;
            for (int j = 0; j < matrix[i].length; j++) {
                sum += matrix[i][j] * vector[j];
            }
            result[i] = sum % 26;
        }
        return result;
    }

    private static int[][] findModularInverse(int[][] matrix, int mod) {
        int determinant = calculateDeterminant(matrix, matrixSize) % mod;
        determinant = (determinant + mod) % mod;

        int detInverse = modularInverse(determinant, mod);
        if (detInverse == -1) return null;

        int[][] adjugate = findAdjugate(matrix);
        int[][] inverse = new int[matrixSize][matrixSize];

        for (int i = 0; i < matrixSize; i++) {
            for (int j = 0; j < matrixSize; j++) {
                inverse[i][j] = (adjugate[i][j] * detInverse) % mod;
                if (inverse[i][j] < 0) inverse[i][j] += mod;
            }
        }
        return inverse;
    }

    private static int calculateDeterminant(int[][] matrix, int size) {
        if (size == 1) return matrix[0][0];

        int determinant = 0;
        int sign = 1;
        for (int i = 0; i < size; i++) {
            int[][] subMatrix = getSubMatrix(matrix, 0, i, size);
            determinant += sign * matrix[0][i] * calculateDeterminant(subMatrix, size - 1);
            sign = -sign;
        }
        return determinant;
    }

    private static int[][] getSubMatrix(int[][] matrix, int excludingRow, int excludingCol, int size) {
        int[][] subMatrix = new int[size - 1][size - 1];
        int r = 0, c;
        for (int i = 0; i < size; i++) {
            if (i == excludingRow) continue;
            c = 0;
            for (int j = 0; j < size; j++) {
                if (j == excludingCol) continue;
                subMatrix[r][c++] = matrix[i][j];
            }
            r++;
        }
        return subMatrix;
    }

    private static int[][] findAdjugate(int[][] matrix) {
        int[][] adjugate = new int[matrixSize][matrixSize];
        for (int i = 0; i < matrixSize; i++) {
            for (int j = 0; j < matrixSize; j++) {
                int[][] subMatrix = getSubMatrix(matrix, i, j, matrixSize);
                adjugate[j][i] = (int) Math.pow(-1, i + j) * calculateDeterminant(subMatrix, matrixSize - 1);
            }
        }
        return adjugate;
    }

    private static int modularInverse(int num, int mod) {
        num = (num % mod + mod) % mod;
        for (int x = 1; x < mod; x++) {
            if ((num * x) % mod == 1) return x;
        }
        return -1;
    }

    private static String prepareText(String text, int size) {
        text = text.replaceAll("[^A-Z]", "");
        while (text.length() % size != 0) {
            text += "X";
        }
        return text;
    }
}
Leave a Comment