1// Aim: Program to perform Substitution cipher (Substitution Cipher).
2import java.util.*;
3import java.util.Scanner;
4
5public class cipher {
6
7 public static String encrypt(String text, int shift) {
8 StringBuilder result = new StringBuilder();
9 for(char c : text.toCharArray()){
10 if(Character.isUpperCase(c)){
11 result.append((char) (((c-'A'+shift)%26)+'A'));
12 }else if(Character.isLowerCase(c)) {
13 result.append((char) (((c-'a'+shift)%26)+'a'));
14 }else{
15 result.append(c);
16 }
17 }
18 return result.toString();
19 }
20
21 public static String decrypt(String text, int shift) {
22 return encrypt(text,26-(shift%26));
23 }
24
25 private static String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
26
27 public static String monoencrypt(String plainText, String key) {
28 plainText = plainText.toUpperCase();
29 StringBuilder cipherText = new StringBuilder();
30 for (char c : plainText.toCharArray()) {
31 int idx = ALPHABET.indexOf(c);
32 if (idx!=-1){
33 cipherText.append(key.charAt(idx));
34 }else{
35 cipherText.append(c);
36 }
37 }
38 return cipherText.toString();
39 }
40
41 public static String monodecrypt(String cipherText, String key) {
42 cipherText = cipherText.toUpperCase();
43 StringBuilder plainText = new StringBuilder();
44 for (char c : cipherText.toCharArray()) {
45 int idx = key.indexOf(c);
46 if(idx != -1){
47 plainText.append(ALPHABET.charAt(idx));
48 }else{
49 plainText.append(c);
50 }
51 }
52 return plainText.toString();
53 }
54
55 public static int modInverse(int a, int m) {
56 a = a % m;
57 for (int x = 1; x < m; x++) {
58 if ((a * x) % m == 1)
59 return x;
60 }
61 return -1;
62 }
63
64
65 public static String hillEncrypt(String plaintext, int[][] keyMatrix) {
66 plaintext = plaintext.toUpperCase();
67 int[] vector = new int[3];
68 for (int i = 0; i < 3; i++) {
69 vector[i] = plaintext.charAt(i) - 'A';
70 }
71
72 int[] result = new int[3];
73 for (int i = 0; i < 3; i++) {
74 result[i] = 0;
75 for (int j = 0; j < 3; j++) {
76 result[i] += keyMatrix[i][j] * vector[j];
77 }
78 result[i] %= 26;
79 }
80
81 StringBuilder encrypted = new StringBuilder();
82 for (int val : result) {
83 encrypted.append((char) (val + 'A'));
84 }
85 return encrypted.toString();
86 }
87
88 public static int determinant(int[][] m) {
89 return m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])
90 - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])
91 + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
92 }
93
94 public static int[][] adjugate(int[][] m) {
95 int[][] adj = new int[3][3];
96
97 adj[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]);
98 adj[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
99 adj[0][2] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
100
101 adj[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
102 adj[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]);
103 adj[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
104
105 adj[2][0] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]);
106 adj[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
107 adj[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]);
108
109 int[][] transpose = new int[3][3];
110 for (int i = 0; i < 3; i++)
111 for (int j = 0; j < 3; j++)
112 transpose[i][j] = adj[j][i];
113
114 return transpose;
115 }
116
117 public static String hillDecrypt(String ciphertext, int[][] keyMatrix) {
118 int det = determinant(keyMatrix);
119 int detInv = modInverse(det % 26, 26);
120 if (detInv == -1)
121 return "Key not invertible. Decryption failed.";
122
123 int[][] adj = adjugate(keyMatrix);
124 int[][] inv = new int[3][3];
125
126 for (int i = 0; i < 3; i++)
127 for (int j = 0; j < 3; j++) {
128 inv[i][j] = (adj[i][j] * detInv) % 26;
129 if (inv[i][j] < 0)
130 inv[i][j] += 26;
131 }
132
133 ciphertext = ciphertext.toUpperCase();
134 int[] vector = new int[3];
135 for (int i = 0; i < 3; i++) {
136 vector[i] = ciphertext.charAt(i) - 'A';
137 }
138
139 int[] result = new int[3];
140 for (int i = 0; i < 3; i++) {
141 result[i] = 0;
142 for (int j = 0; j < 3; j++) {
143 result[i] += inv[i][j] * vector[j];
144 }
145 result[i] %= 26;
146 }
147
148 StringBuilder decrypted = new StringBuilder();
149 for (int val : result) {
150 decrypted.append((char) (val + 'A'));
151 }
152 return decrypted.toString();
153 }
154
155
156 public static void main(String[] args) {
157 Scanner sc = new Scanner(System.in);
158 int ch;
159 do{
160 System.out.println("\n--- Cipher Menu ---\n1. Caesar Cipher\n2. Substitution Cipher\n3. Hill Cipher \n4. Exit\nChoose option: \n");
161
162 ch = sc.nextInt();
163 sc.nextLine();
164 switch(ch){
165 case 1 :
166 System.out.print("Enter text: ");
167 String text = sc.nextLine();
168 System.out.print("Enter shift: ");
169 int shift = sc.nextInt();
170 String encrypted = encrypt(text, shift);
171 String decrypted = decrypt(encrypted, shift);
172 System.out.println("Encrypted: " + encrypted);
173 System.out.println("Decrypted: " + decrypted);
174 break;
175 case 2 :
176 System.out.print("Enter key (26 unique uppercase letters): ");
177 String key = sc.nextLine().toUpperCase();
178 System.out.print("Enter plain text: ");
179 String plainText = sc.nextLine();
180 String monoencrypted = monoencrypt(plainText, key);
181 String monodecrypted = monodecrypt(monoencrypted, key);
182 System.out.println("Encrypted: " + monoencrypted);
183 System.out.println("Decrypted: " + monodecrypted);
184 break;
185 case 3 :
186 System.out.print("Enter 9-letter key: ");
187 String keyStr = sc.nextLine().toUpperCase();
188 if (keyStr.length() != 9) {
189 System.out.println("Key must be 9 letters.");
190 break;
191 }
192 int[][] matrix = new int[3][3];
193 for (int i = 0; i < 9; i++)
194 matrix[i / 3][i % 3] = keyStr.charAt(i) - 'A';
195
196 System.out.print("Enter 3-letter plaintext: ");
197 String plain = sc.nextLine().toUpperCase();
198 if (plain.length() != 3) {
199 System.out.println("Plaintext must be 3 letters.");
200 break;
201 }
202
203 String hillEnc = hillEncrypt(plain, matrix);
204 String hillDec = hillDecrypt(hillEnc, matrix);
205 System.out.println("Encrypted: " + hillEnc);
206 System.out.println("Decrypted: " + hillDec);
207 break;
208 case 4:
209 System.out.println("Exiting.");
210 break;
211
212 default:
213 System.out.println("Invalid option.");
214 }
215 }while(ch != 4);
216 sc.close();
217 }
218}
219