The affine cipher is a simple mathematical substitution cipher. If you're interested in the details behind how it works, this page goes further into detail.
After writing a program to encrypt and decrypt text using the affine cipher, I felt that it seemed needlessly cluttered. I have also noticed that there are no questions related to the affine cipher on Code Review, at least not for C++.
Here's the code:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <cmath>
int gcd(int a, int b);
int modInverse(int a, int b); // from https://rosettacode.org/wiki/Modular_inverse#C.2B.2B
int main(){
std::string choice;
do{
std::cout << "Encrypt or Decrypt? [e/d] = ";
std::getline(std::cin, choice);
std::transform(choice.begin(), choice.end(), choice.begin(), ::tolower);
} while(choice.length() > 1 || choice != "e" && choice != "d");
std::cout << "\nInput string: ";
std::string input;
std::getline(std::cin, input);
int a, b;
do{
std::cout << "\na and b must be coprime\na = ";
std::cin >> a;
std::cout << "b = ";
std::cin >> b;
} while(std::cin.fail() || gcd(a,b) != 1);
std::cout << '\n';
if(choice == "e"){
for(int i = 0; i < input.length(); ++i){
if(input[i] >= 'a' && input[i] <= 'z'){
std::cout << (char)((a * (input[i] - 'a') + b) % 26 + 'a');
} else if(input[i] >= 'A' && input[i] <= 'Z'){
std::cout << (char)((a * (input[i] - 'A') + b) % 26 + 'A');
} else{
std::cout << input[i];
}
}
} else{
for(int i = 0; i < input.length(); ++i){
if(input[i] >= 'a' && input[i] <= 'z'){
std::cout << (char)(modInverse(a, 26) * (26 + input[i] - 'a' - b) % 26 + 'a');
} else if(input[i] >= 'A' && input[i] <= 'Z'){
std::cout << (char)(modInverse(a, 26) * (26 + input[i] - 'A' - b) % 26 + 'A');
} else{
std::cout << input[i];
}
}
}
std::cout << '\n';
return 0;
}
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
int modInverse(int a, int b){
int b0 = b, t, q;
int x0 = 0, x1 = 1;
if (b == 1) return 1;
while (a > 1) {
q = a / b;
t = b, b = a % b, a = t;
t = x0, x0 = x1 - q * x0, x1 = t;
}
if (x1 < 0) x1 += b0;
return x1;
}
Here is an example output for the encryption side:
Encrypt or Decrypt? [e/d] = e
Input string: Hello World!
a and b must be coprime
a = 5
b = 9
Sdmmb Pbqmy!
And here is an example output for the decryption side:
Encrypt or Decrypt? [e/d] = d
Input string: Sdmmb Pbqmy!
a and b must be coprime
a = 5
b = 9
Hello World!
I am using the modInverse()
function from Rosetta Code. This is quasi-related to my ongoing series of classical ciphers. So far I have done a simple Caesar cipher and an Atbash cipher.
How can I improve this code, both for readability and for efficiency?