31

I want to calculate ab mod n for use in RSA decryption. My code (below) returns incorrect answers. What is wrong with it?

unsigned long int decrypt2(int a,int b,int n)
{
    unsigned long int res = 1;

    for (int i = 0; i < (b / 2); i++)
    {
        res *= ((a * a) % n);
        res %= n;
    }

    if (b % n == 1)
        res *=a;

    res %=n;
    return res;
}
Pops
  • 30,199
  • 37
  • 136
  • 151
Moein Hosseini
  • 4,309
  • 15
  • 68
  • 106

14 Answers14

69

You can try this C++ code. I've used it with 32 and 64-bit integers. I'm sure I got this from SO.

template <typename T>
T modpow(T base, T exp, T modulus) {
  base %= modulus;
  T result = 1;
  while (exp > 0) {
    if (exp & 1) result = (result * base) % modulus;
    base = (base * base) % modulus;
    exp >>= 1;
  }
  return result;
}

You can find this algorithm and related discussion in the literature on p. 244 of

Schneier, Bruce (1996). Applied Cryptography: Protocols, Algorithms, and Source Code in C, Second Edition (2nd ed.). Wiley. ISBN 978-0-471-11709-4.


Note that the multiplications result * base and base * base are subject to overflow in this simplified version. If the modulus is more than half the width of T (i.e. more than the square root of the maximum T value), then one should use a suitable modular multiplication algorithm instead - see the answers to Ways to do modulo multiplication with primitive types.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Blastfurnace
  • 18,411
  • 56
  • 55
  • 70
  • 1
    +1 (I meant to leave a comment earlier) this was very helpful to this [question](https://stackoverflow.com/questions/22703398/inconsistencies-when-using-cmaths-fmod-c) it would be great to find the original source. – Shafik Yaghmour Mar 28 '14 at 09:52
  • 7
    But what if `modulus > sqrt(std::numeric_limits::max())`? In that case `(result * base)` can overflow, and the result will be incorrect. – Ruud May 31 '14 at 14:09
  • 3
    @RuudvA: To avoid that you can replace those multiplications with your preferred modular multiplication function. For example: [Ways to do modulo multiplication with primitive types](http://stackoverflow.com/q/12168348/445976) – Blastfurnace May 31 '14 at 14:22
  • By definition, it is not possible for `modulus` to have a value that exceeds the maximum its type can represent. – Peter Oct 09 '16 at 07:11
  • For a full explanation, see: https://en.wikipedia.org/wiki/Modular_exponentiation – Gene Olson Jun 30 '17 at 00:53
  • Also: https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/modular-exponentiation – Gene Olson Jun 30 '17 at 00:56
  • 1
    `T result = 1;` --> `T result = modulus > 1;` or `result = 1%modulus` to properly function with `modpow(x, 0, 1)`. – chux - Reinstate Monica Jan 15 '18 at 23:42
  • Add `if (base==0) return 0;` in loop may quickly get result. – ToyAuthor X Aug 23 '18 at 06:10
  • 1
    How does this code avoid overflowing the range of `T` in the calculation of `result * base` and `base * base`? – Toby Speight Dec 06 '18 at 13:06
  • @TobySpeight I mentioned that in a comment above. You can use modular multiplication ([SO example link](https://stackoverflow.com/q/12168348/445976)). – Blastfurnace Dec 06 '18 at 15:04
  • @Blastfurnace: since that wasn't at all obvious, I've edited your answer to incorporate that link. – Toby Speight Dec 06 '18 at 17:38
17

In order to calculate pow(a,b) % n to be used for RSA decryption, the best algorithm I came across is Primality Testing 1) which is as follows:

 int modulo(int a, int b, int n){
    long long x=1, y=a; 
    while (b > 0) {
        if (b%2 == 1) {
            x = (x*y) % n; // multiplying with base
        }
        y = (y*y) % n; // squaring the base
        b /= 2;
    }
    return x % n;
}

See below reference for more details.


1) Primality Testing : Non-deterministic Algorithms – topcoder

Wolf
  • 9,679
  • 7
  • 62
  • 108
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • You seem to be assuming that `long long` has a wider range than `int`. There's no such guarantee in either C or C++, so this code is still subject to overflow. – Toby Speight Dec 06 '18 at 13:05
14

Usually it's something like this:

while (b)
{
    if (b % 2) { res = (res * a) % n; }

    a = (a * a) % n;
    b /= 2;
}

return res;
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
7

The only actual logic error that I see is this line:

if (b % n == 1)

which should be this:

if (b % 2 == 1)

But your overall design is problematic: your function performs O(b) multiplications and modulus operations, but your use of b / 2 and a * a implies that you were aiming to perform O(log b) operations (which is usually how modular exponentiation is done).

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • Another logic error I think is: If `a == 0` the result is `1` instead of `0`. And `a` should be assigned to a temporary 64 bit variable which in turn is used for the multiplication – to avoid the overflow. – Christian Ammer Dec 14 '11 at 08:58
  • @ChristianAmmer: Re: if `a == 0`. Actually no, because as long as `b > 0`, `res` will be multiplied by `a` or `a * a` at least once. (And if `b == 0`, then `1` is a perfectly valid return value even if `a == 0`.) Re: assigning `a` to a temporary 64-bit variable: I suppose so. Other commenters had already pointed out that 32-bit integers are not enough to use this for realistic RSA encryption, so my answer assumed that this function was just for trying it out with small numbers and getting a handle on how it worked. Maybe I should have made that explicit? – ruakh Dec 14 '11 at 13:03
4

Doing the raw power operation is very costly, hence you can apply the following logic to simplify the decryption.

From here,

Now say we want to encrypt the message m = 7,
c = m^e mod n = 7^3 mod 33 = 343 mod 33 = 13.
Hence the ciphertext c = 13.

To check decryption we compute
m' = c^d mod n = 13^7 mod 33 = 7.
Note that we don't have to calculate the full value of 13 to the power 7 here. We can make use of the fact that
a = bc mod n = (b mod n).(c mod n) mod n
so we can break down a potentially large number into its components and combine the results of easier, smaller calculations to calculate the final value.

One way of calculating m' is as follows:-
Note that any number can be expressed as a sum of powers of 2. So first compute values of
13^2, 13^4, 13^8, ... by repeatedly squaring successive values modulo 33. 13^2 = 169 ≡ 4, 13^4 = 4.4 = 16, 13^8 = 16.16 = 256 ≡ 25.
Then, since 7 = 4 + 2 + 1, we have m' = 13^7 = 13^(4+2+1) = 13^4.13^2.13^1
≡ 16 x 4 x 13 = 832 ≡ 7 mod 33

bragboy
  • 34,892
  • 30
  • 114
  • 171
2

Calculating pow(a,b) mod n

  1. A key problem with OP's code is a * a. This is int overflow (undefined behavior) when a is large enough. The type of res is irrelevant in the multiplication of a * a.

    The solution is to ensure either:

    • the multiplication is done with 2x wide math or
    • with modulus n, n*n <= type_MAX + 1
  2. There is no reason to return a wider type than the type of the modulus as the result is always represent by that type.

    // unsigned long int decrypt2(int a,int b,int n)
    int decrypt2(int a,int b,int n)
    
  3. Using unsigned math is certainly more suitable for OP's RSA goals.


Also see Modular exponentiation without range restriction

// (a^b)%n
// n != 0

// Test if unsigned long long at least 2x values bits as unsigned
#if ULLONG_MAX/UINT_MAX  - 1 > UINT_MAX
unsigned decrypt2(unsigned a, unsigned b, unsigned n) {
  unsigned long long result = 1u % n;  // Insure result < n, even when n==1
  while (b > 0) {
    if (b & 1) result = (result * a) % n;
    a = (1ULL * a * a) %n;
    b >>= 1;
  }
  return (unsigned) result;
}

#else
unsigned decrypt2(unsigned a, unsigned b, unsigned n) {
  // Detect if  UINT_MAX + 1 < n*n
  if (UINT_MAX/n < n-1) {
    return TBD_code_with_wider_math(a,b,n);
  }
  a %= n;
  unsigned result = 1u % n;
  while (b > 0) {
    if (b & 1) result = (result * a) % n;
    a = (a * a) % n;
    b >>= 1;
  }
  return result;
}

#endif
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    This is the only answer at present that identifies the cause of the problem and suggests an appropriate resolution. The other answers are all subject to overflow. – Toby Speight Dec 06 '18 at 13:03
2

Are you trying to calculate (a^b)%n, or a^(b%n) ?

If you want the first one, then your code only works when b is an even number, because of that b/2. The "if b%n==1" is incorrect because you don't care about b%n here, but rather about b%2.

If you want the second one, then the loop is wrong because you're looping b/2 times instead of (b%n)/2 times.

Either way, your function is unnecessarily complex. Why do you loop until b/2 and try to multiply in 2 a's each time? Why not just loop until b and mulitply in one a each time. That would eliminate a lot of unnecessary complexity and thus eliminate potential errors. Are you thinking that you'll make the program faster by cutting the number of times through the loop in half? Frankly, that's a bad programming practice: micro-optimization. It doesn't really help much: You still multiply by a the same number of times, all you do is cut down on the number of times testing the loop. If b is typically small (like one or two digits), it's not worth the trouble. If b is large -- if it can be in the millions -- then this is insufficient, you need a much more radical optimization.

Also, why do the %n each time through the loop? Why not just do it once at the end?

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
Jay
  • 26,876
  • 10
  • 61
  • 112
  • Doing the modulo at the end --> `res` would get unnecessary big and overflow (what it does in his example anyway). Looping until b/2 --> Only half of the iterations are necessary because the compiler would optimize and precalculate `(a*a) % n`. – Christian Ammer Dec 13 '11 at 21:36
0

Here is another way. Remember that when we find modulo multiplicative inverse of a under mod m. Then

a and m must be coprime with each other.

We can use gcd extended for calculating modulo multiplicative inverse.

For computing ab mod m when a and b can have more than 105 digits then its tricky to compute the result.

Below code will do the computing part :

#include <iostream>
#include <string>
using namespace std;
/*
*   May this code live long.
*/
long pow(string,string,long long);
long pow(long long ,long long ,long long);
int main() {
    string _num,_pow;
    long long _mod;
    cin>>_num>>_pow>>_mod;
    //cout<<_num<<" "<<_pow<<" "<<_mod<<endl;
    cout<<pow(_num,_pow,_mod)<<endl;
   return 0;
}
long pow(string n,string p,long long mod){
    long long num=0,_pow=0;
    for(char c: n){
        num=(num*10+c-48)%mod;
    }
    for(char c: p){
        _pow=(_pow*10+c-48)%(mod-1);
    }
    return pow(num,_pow,mod);
}
long pow(long long a,long long p,long long mod){
    long res=1;
    if(a==0)return 0;
    while(p>0){
        if((p&1)==0){
            p/=2;
            a=(a*a)%mod;
        }
        else{
            p--;
            res=(res*a)%mod;
        }
    }
    return res;
}
 

This code works because ab mod m can be written as (a mod m)b mod m-1 mod m.

Hope it helped { :)

Udesh
  • 2,415
  • 2
  • 22
  • 32
0

int's are generally not enough for RSA (unless you are dealing with small simplified examples)

you need a data type that can store integers up to 2256 (for 256-bit RSA keys) or 2512 for 512-bit keys, etc

zed_0xff
  • 32,417
  • 7
  • 53
  • 72
-1

use fast exponentiation maybe..... gives same o(log n) as that template above

    int power(int base, int exp,int mod)
{
    if(exp == 0)
     return 1;

    int p=power(base, exp/2,mod);
    p=(p*p)% mod;
    return (exp%2 == 0)?p:(base * p)%mod;
}
-1

This(encryption) is more of an algorithm design problem than a programming one. The important missing part is familiarity with modern algebra. I suggest that you look for a huge optimizatin in group theory and number theory. If n is a prime number, pow(a,n-1)%n==1 (assuming infinite digit integers).So, basically you need to calculate pow(a,b%(n-1))%n; According to group theory, you can find e such that every other number is equivalent to a power of e modulo n. Therefore the range [1..n-1] can be represented as a permutation on powers of e. Given the algorithm to find e for n and logarithm of a base e, calculations can be significantly simplified. Cryptography needs a tone of math background; I'd rather be off that ground without enough background.

Red.Wave
  • 2,790
  • 11
  • 17
-1

For my code a^k mod n in php:

function pmod(a, k, n)
{
    if (n==1) return 0;
    power = 1;
    for(i=1; i<=k; $i++)
    {
        power = (power*a) % n;
    }
    return power;
}
Nam Le
  • 182
  • 1
  • 8
-2

I'm using this function:

int CalculateMod(int base, int exp ,int mod){
    int result;
    result = (int) pow(base,exp);
    result = result % mod;
    return result;
}

I parse the variable result because pow give you back a double, and for using mod you need two variables of type int, anyway, in a RSA decryption, you should just use integer numbers.

I.Mateos
  • 9
  • 5
  • If the result of pow(base, exp) is larger than MAXINT, then you will get an exception when you convert back to an int. Even if you didn't get an exception, you would be taking the mod of the wrong number. – Gene Olson Jun 30 '17 at 00:46
-2
#include <cmath>
...
static_cast<int>(std::pow(a,b))%n

but my best bet is you are overflowing int (IE: the number is two large for the int) on the power I had the same problem creating the exact same function.

e-sushi
  • 13,786
  • 10
  • 38
  • 57
111111
  • 15,686
  • 6
  • 47
  • 62