fork download
  1. // Hill Cipher
  2.  
  3. #include <iostream>
  4. #include <vector>
  5. #include <cctype>
  6. using namespace std;
  7.  
  8. // Convert character to number (A=0, ..., Z=25)
  9. int charToInt(char c) {
  10. return toupper(c) - 'A';
  11. }
  12.  
  13. // Convert number to uppercase character
  14. char intToChar(int n) {
  15. return 'A' + (n % 26);
  16. }
  17.  
  18. // Modulo 26 (handles negative numbers too)
  19. int mod26(int n) {
  20. return (n % 26 + 26) % 26;
  21. }
  22.  
  23. // Multiply 3x3 matrix with 3x1 vector
  24. vector<int> multiplyMatrix(const vector<vector<int>>& mat, const vector<int>& vec) {
  25. vector<int> res(3, 0);
  26. for (int i = 0; i < 3; ++i)
  27. for (int j = 0; j < 3; ++j)
  28. res[i] = mod26(res[i] + mat[i][j] * vec[j]);
  29. return res;
  30. }
  31.  
  32. // Calculate determinant of 3x3 matrix
  33. int determinant(const vector<vector<int>>& m) {
  34. int det = m[0][0]*(m[1][1]*m[2][2] - m[1][2]*m[2][1]) -
  35. m[0][1]*(m[1][0]*m[2][2] - m[1][2]*m[2][0]) +
  36. m[0][2]*(m[1][0]*m[2][1] - m[1][1]*m[2][0]);
  37. return mod26(det);
  38. }
  39.  
  40. // Find modular inverse of a number modulo 26
  41. int modInverse(int det) {
  42. det = (det % 26 + 26) % 26; // Ensure positive mod
  43. for (int i = 1; i < 26; ++i) {
  44. if ((det * i) % 26 == 1) return i;
  45. }
  46. return -1; // No modular inverse exists
  47.  
  48. }
  49.  
  50. // Adjugate (cofactor transpose) of 3x3 matrix
  51. vector<vector<int>> adjugate(const vector<vector<int>>& m) {
  52. vector<vector<int>> adj(3, vector<int>(3));
  53.  
  54. adj[0][0] = mod26(m[1][1]*m[2][2] - m[1][2]*m[2][1]);
  55. adj[0][1] = mod26(-(m[0][1]*m[2][2] - m[0][2]*m[2][1]));
  56. adj[0][2] = mod26(m[0][1]*m[1][2] - m[0][2]*m[1][1]);
  57.  
  58. adj[1][0] = mod26(-(m[1][0]*m[2][2] - m[1][2]*m[2][0]));
  59. adj[1][1] = mod26(m[0][0]*m[2][2] - m[0][2]*m[2][0]);
  60. adj[1][2] = mod26(-(m[0][0]*m[1][2] - m[0][2]*m[1][0]));
  61.  
  62. adj[2][0] = mod26(m[1][0]*m[2][1] - m[1][1]*m[2][0]);
  63. adj[2][1] = mod26(-(m[0][0]*m[2][1] - m[0][1]*m[2][0]));
  64. adj[2][2] = mod26(m[0][0]*m[1][1] - m[0][1]*m[1][0]);
  65.  
  66. // Transpose for adjugate
  67. swap(adj[0][1], adj[1][0]);
  68. swap(adj[0][2], adj[2][0]);
  69. swap(adj[1][2], adj[2][1]);
  70.  
  71. return adj;
  72. }
  73.  
  74. // Inverse of 3x3 matrix modulo 26
  75. vector<vector<int>> inverseMatrix(const vector<vector<int>>& matrix) {
  76. int det = determinant(matrix);
  77. int detInv = modInverse(det);
  78.  
  79. if (detInv == -1) {
  80. cout << "Matrix is not invertible under mod 26.\n";
  81. return {};
  82. }
  83.  
  84. vector<vector<int>> adj = adjugate(matrix);
  85. vector<vector<int>> inv(3, vector<int>(3));
  86. for (int i = 0; i < 3; ++i)
  87. for (int j = 0; j < 3; ++j)
  88. inv[i][j] = mod26(adj[i][j] * detInv);
  89. return inv;
  90. }
  91.  
  92. // Encrypt plaintext using Hill Cipher
  93. string encrypt(const string& plaintext, const vector<vector<int>>& key) {
  94. string cleanText = "";
  95. for (char c : plaintext)
  96. if (isalpha(c)) cleanText += toupper(c);
  97.  
  98. // Pad with 'X' if not multiple of 3
  99. while (cleanText.size() % 3 != 0)
  100. cleanText += 'X';
  101.  
  102. string cipher = "";
  103. for (size_t i = 0; i < cleanText.size(); i += 3) {
  104. vector<int> block = {
  105. charToInt(cleanText[i]),
  106. charToInt(cleanText[i+1]),
  107. charToInt(cleanText[i+2])
  108. };
  109. vector<int> res = multiplyMatrix(key, block);
  110. for (int val : res)
  111. cipher += intToChar(val);
  112. }
  113.  
  114. return cipher;
  115. }
  116.  
  117. // Decrypt cipher using Hill Cipher
  118. string decrypt(const string& cipher, const vector<vector<int>>& key) {
  119. vector<vector<int>> invKey = inverseMatrix(key);
  120. if (invKey.empty()) return "";
  121.  
  122. string plain = "";
  123. for (size_t i = 0; i < cipher.size(); i += 3) {
  124. vector<int> block = {
  125. charToInt(cipher[i]),
  126. charToInt(cipher[i+1]),
  127. charToInt(cipher[i+2])
  128. };
  129. vector<int> res = multiplyMatrix(invKey, block);
  130. for (int val : res)
  131. plain += intToChar(val);
  132. }
  133.  
  134. return plain;
  135. }
  136.  
  137. int main() {
  138. vector<vector<int>> key = {
  139. {6, 24, 1},
  140. {13, 16, 10},
  141. {20, 17, 15}
  142. }; // GYBNQKURP
  143.  
  144. string text;
  145. cout << "Enter the plain text: ";
  146. getline(cin, text);
  147.  
  148. string encrypted = encrypt(text, key);
  149. cout << "Encrypted: " << encrypted << endl;
  150.  
  151. string decrypted = decrypt(encrypted, key);
  152. cout << "Decrypted: " << decrypted << endl;
  153.  
  154. return 0;
  155. }
  156.  
Success #stdin #stdout 0.01s 5288KB
stdin
Standard input is empty
stdout
Enter the plain text: Encrypted: 
Decrypted: