── Vigenere ──────────────────────────────────────────────────
| 22 | |
| 23 | // ── Vigenere ────────────────────────────────────────────────── |
| 24 | std::string vigenere(const std::string& text, const std::string& key, bool decrypt) { |
| 25 | if (key.empty()) throw std::runtime_error("Key cannot be empty"); |
| 26 | std::string result; |
| 27 | int ki = 0; |
| 28 | for (char c : text) { |
| 29 | if (std::isalpha(c)) { |
| 30 | char base = std::isupper(c) ? 'A' : 'a'; |
| 31 | char kc = std::toupper(key[ki % key.size()]) - 'A'; |
| 32 | if (decrypt) { |
| 33 | result += (char)((c - base - kc + 26) % 26 + base); |
| 34 | } else { |
| 35 | result += (char)((c - base + kc) % 26 + base); |
| 36 | } |
| 37 | ki++; |
| 38 | } else { |
| 39 | result += c; |
| 40 | } |
| 41 | } |
| 42 | return result; |
| 43 | } |
| 44 | |
| 45 | // ── XOR ─────────────────────────────────────────────────────── |
| 46 | std::string xorCipher(const std::string& text, const std::string& key) { |