fork download
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. // 모듈러 연산에서 음수가 나올 경우 양수로 보정해주는 함수
  8. int mod26(int a) {
  9. return (a % 26 + 26) % 26;
  10. }
  11.  
  12. // 모듈로 26에 대한 곱셈의 역원 구하기 (주어진 det에 대해 det * x ≡ 1 (mod 26) 인 x 찾기)
  13. int modInverse(int a, int m = 26) {
  14. a = mod26(a);
  15. for (int x = 1; x < m; x++) {
  16. if ((a * x) % m == 1)
  17. return x;
  18. }
  19. return -1; // 역원이 존재하지 않는 경우 (키로 사용할 수 없음)
  20. }
  21.  
  22. // 2x2 행렬의 역행렬 구하기 (모듈로 26 기준)
  23. bool getInverseMatrix(int key[2][2], int invKey[2][2]) {
  24. // 행렬식(Determinant) 계산: ad - bc
  25. int det = key[0][0] * key[1][1] - key[0][1] * key[1][0];
  26. int detInv = modInverse(det, 26);
  27.  
  28. if (detInv == -1) {
  29. return false; // 행렬식의 역원이 없으면 복호화 불가능
  30. }
  31.  
  32. // 수반행렬을 이용한 역행렬 계산 (mod 26 적용)
  33. invKey[0][0] = mod26(key[1][1] * detInv);
  34. invKey[0][1] = mod26(-key[0][1] * detInv);
  35. invKey[1][0] = mod26(-key[1][0] * detInv);
  36. invKey[1][1] = mod26(key[0][0] * detInv);
  37.  
  38. return true;
  39. }
  40.  
  41. // 힐 암호 핵심 연산 (암호화/복호화 공용)
  42. string processHillCipher(string text, int key[2][2]) {
  43. string result = "";
  44.  
  45. // 2글자씩 쌍을 지어 행렬 곱셈 수행
  46. for (size_t i = 0; i < text.length(); i += 2) {
  47. int p1 = text[i] - 'A';
  48. int p2 = text[i+1] - 'A';
  49.  
  50. int c1 = mod26(key[0][0] * p1 + key[0][1] * p2);
  51. int c2 = mod26(key[1][0] * p1 + key[1][1] * p2);
  52.  
  53. result += (c1 + 'A');
  54. result += (c2 + 'A');
  55. }
  56. return result;
  57. }
  58.  
  59. int main() {
  60. // 1. 사용할 키 행렬 정의 (역행렬이 존재하는지 확인 필요)
  61. // 예시 키: [[5, 8], [17, 3]] -> det = 15 - 136 = -121 ≡ 9 (mod 26). 9의 역원은 3으로 존재함.
  62. int key[2][2] = {
  63. {5, 8},
  64. {17, 3}
  65. };
  66.  
  67. int invKey[2][2];
  68. if (!getInverseMatrix(key, invKey)) {
  69. cout << "오류: 선택한 키 행렬은 역행렬이 존재하지 않아 복호화할 수 없습니다!" << endl;
  70. return 1;
  71. }
  72.  
  73. // 2. 평문 입력
  74. string plaintext = "yaho";
  75. cout << "원래 평문: " << plaintext << endl;
  76.  
  77. // 글자 수가 홀수이면 X를 붙여 짝수로 맞춤
  78. if (plaintext.length() % 2 != 0) {
  79. plaintext += 'X';
  80. }
  81.  
  82. // 3. 암호화 진행
  83. string ciphertext = processHillCipher(plaintext, key);
  84. cout << "암호화된 텍스트: " << ciphertext << endl;
  85.  
  86. // 4. 복호화 진행 (역행렬 사용)
  87. string decryptedText = processHillCipher(ciphertext, invKey);
  88. cout << "복호화된 텍스트: " << decryptedText << endl;
  89.  
  90. return 0;
  91. }
Success #stdin #stdout 0.01s 5308KB
stdin
Standard input is empty
stdout
원래 평문: yaho
암호화된 텍스트: QIRV
복호화된 텍스트: EGNU