Untitled
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