0

I have written the code for RSA in C++ on Ubuntu. It was working fine on that, it's working fine on Windows Dev C++ as well, but it doesn't show the character properly.

Here is the code :

#include<iostream>
#include<stdlib.h>                 // for rand()
#include<math.h>                   // for floor function
#include<string.h>             
using namespace std;


//function to check whether a number is prime or not
int  check_prime(int number)
{
    int count = 0;
    for(int i = 2; i<number + 1; i++)
    {
        if(number%i == 0)
        {
            count++;
        }
    }
    if(count>2)
    {
        return 0;
    }
    else
    {
        return 1;
    }

}

//function to generate a random prime number
int generate_random_prime()
{
    int temp;
    while(1)
    {
        temp = rand() % 50;
        if(check_prime(temp) == 1)
        {
            return  temp;
        }
    }
}

int gcd(int a, int b)
{
    int temp;
    while(b != 0)
    {
        temp = b;
        b = a%b;
        a = temp;
    }
    return a;
}

//  Extended Euclid GCD to find d such de congruent to 1
int extended_gcd(int a, int b)
{
    int d, x, y, r, q;
    if(b == 0)
    {
        d = a;
        x = 1;
        y = 0;
        cout << "\n d= " << d << " x= " << x << " y= " << y << "\n";
    }
    int x2, x1, y2, y1;
    x2 = 1;
    x1 = 0;
    y2 = 0;
    y1 = 1;
    while(b > 0)
    {
        q = floor(a / b);
        r = a - q*b;
        x = x2 - q*x1;
        y = y2 - q*y1;
        a = b;
        b = r;
        x2 = x1;
        x1 = x;
        y2 = y1;
        y1 = y;
    }
    d = a;
    x = x2;
    y = y2;
    return x2;
}

//returns a^b mod n using square and multiply method
int modular_exponentiation(int a, int b, int n)
{
    if(a == 1)
    {
        return 0;
    }
    int c = 1;
    for(int i = 1; i < b + 1; i++)
    {
        c = (c*a) % n;
    }
    return c;
}


//cipher text = (message^e) %n
int cipher_text(int m, int e, int n)
{
    return modular_exponentiation(m, e, n);
}

//decrypted_text= (cipher^d)%n
int decrypt_cipher(int c, int d, int n)
{
    return modular_exponentiation(c, d, n);
}

int main()
{

    // generating two random prime p and q
    int p = generate_random_prime();
    int q = generate_random_prime();

    cout << "Prime p : " << p << "and  q : " << q << "\n";

    int n = p*q;
    cout << "n=p*q = " << n << "\n";
    //calculating Euler Totient for prime p and q
    int euler_phi = (p - 1)*(q - 1);
    cout << "Euler totient is : " << euler_phi << "\n";

    int d, e;
    // calculating e such that 1<e<euler_phi and gcd(n,euler_phi)=1
    while(1)
    {
        e = rand() % (euler_phi - 1 + 1) + 1;
        if(gcd(euler_phi, e) == 1)
        {
            break;
        }
    }

    cout << "e value is : " << e << "\n";

    //calculating d such that ed congruent 1, ed=1
    d = extended_gcd(e, euler_phi);
    //d=5;
    cout << "d value is : " << d << "\n";

    //storing the message to be encrypted as char array and encrypting each char element
    char message[20];
    int cipher[20];
    cout << "Enter the message to be encrypted : ";
    cin >> message;


    cout << "Message to be encrypted is : " << message << "\n";

    int size = strlen(message);

    //calculating cipher text c
    for(int i = 0; i < size; i++)
    {
        cipher[i] = cipher_text(int(message[i]), e, n);
    }

    cout << "Cipher text is : ";
    for(int i = 0; i < size; i++)
    {
        cout << cipher[i] << " ";
    }

    char message_decrypted[size];
    //decrypting cipher text
    for(int i = 0; i < size; i++)
    {
        message_decrypted[i] = decrypt_cipher(cipher[i], d, n);
    }

    cout << "\nDecrypted message is : ";
    for(int i = 0; i < size; i++)
    {
        cout << message_decrypted[i];
    }
    cout << "\n";

    return 0;
}

I have tried the code on DevC++ and using g++. Check the images : Image 1

Image using g++ compiler Image 2

I need a way to print the char to be displayed properly.

I think that message_decrypted[i]=decrypt_cipher(cipher[i],d,n); needs to be changed to print the character properly in Devcpp

Here is the link to the code in online IDE where it works fine https://repl.it/@shubhamjohar/RSA

HMD
  • 2,202
  • 6
  • 24
  • 37
  • 1
    Beside your problem, Please consider choosing meaningful names for your variables, This kind of naming is very confusing in reviews, Specially when someone else going to read it. – HMD Apr 11 '18 at 06:19
  • The `floor` in `floor(a / b)` is pointless - all it does is convert an integer to a float, which you don't want. – molbdnilo Apr 11 '18 at 07:37
  • `extended_gcd` seems wrong; `extended_gcd(2,3)` is -1, and `extended_gcd(2,1)` is 0. (There's a bit of seemingly unnecessary code in that function - did a piece of it go missing?) – molbdnilo Apr 11 '18 at 08:22

2 Answers2

3

When your main routine invokes

decrypt_cipher(cipher[i], d, n);

cipher[0] is 386 as matching your output above. d is -179. And n is 697

The corresponding call into modular_exponentiation(a=386, b=-179, n=697) results in this for-loop getting skipped:

for (int i = 1; i<b + 1; i++) {
    c = (c*a) % n;
}

Because i < (b + 1) evaluates to (1 < -178), which evaluates to false.

Therefore, your modular_exponentiation returns 1, which is an unprintable character.

Same applies for the subsequent calls to decrypt_cipher from main.

I don't know enough about the RSA algorithm to know if your implementation is correct. But when d is negative, that for-loop isn't going to do any loops.

selbie
  • 100,020
  • 15
  • 103
  • 173
  • Also, fwiw, when I compiled your code, I got a warning about an implicit cast from floating point to integer for this line: `q=floor(a/b);` – selbie Apr 11 '18 at 06:35
  • that's a known mis-feature. The code which generates the warning is not aware of the semantics of `floor`, `round`, `lround` and `ceil`. It looks at types only. And it would be a breaking change to fix the return types of those functions. – MSalters Apr 11 '18 at 07:20
-1

Maybe it is incurred by the following expression in your program:

char message_decrypted[size];

There is some standard change related to this usage. please read the following page for more details. https://www.geeksforgeeks.org/variable-length-arrays-in-c-and-c/

Or try to use something like new char[size] to allocate memory dynamically.

gzh
  • 3,507
  • 2
  • 19
  • 23
  • It's never been valid C++. It's a C99 VLA, accepted by g++ as a language extension. Should work fine in Windows with that compiler. – Cheers and hth. - Alf Apr 11 '18 at 06:17
  • @Cheersandhth.-Alf, yes, it is not a valid C++, i.e, not ISO C++, but as shown in https://stackoverflow.com/questions/8593643/does-c-support-variable-length-arrays, it can be compiled with g++ extension. – gzh Apr 11 '18 at 06:28
  • `new char[size]` ? We have a perfectly reasonable `std::string` class. – MSalters Apr 11 '18 at 07:26