Tomek
Tomek

Reputation:

C++ handling very large integers

I am using the RSA Algorithm for encryption/decryption, and in order to decrypt the files you have to deal with some pretty big values. More specifically, things like

P = C^d % n
  = 62^65 % 133

Now that is really the only calculations that ill be doing. I have tried using Matt McCutchen's BigInteger Library, but I am getting a lot of compiler errors during linking, such as:

encryption.o(.text+0x187):encryption.cpp: undefined reference to `BigInteger::BigInteger(int)'

encryption.o(.text+0x302):encryption.cpp: undefined reference to `operator<<(std::ostream&, BigInteger const&)'

encryption.o(.text$_ZNK10BigIntegermlERKS_[BigInteger::operator*(BigInteger const&) const]+0x63):encryption.cpp: undefined reference to `BigInteger::multiply(BigInteger const&, BigInteger const&)'

So I was wondering what would be the best way to go about handling the really big integers that come out of the RSA Algorithm.

I heard that a possibility would be to declare your variables as a double long, so...

long long decryptedCharacter;

but I'm not sure exactly how big of an integer that can store.


Well for example, I try to compile and run the following program using dev C++:

#include iostream

#include "bigint\BigIntegerLibrary.hh"

using namespace std;

int main()
{
    BigInteger a = 65536;
    cout << (a * a * a * a * a * a * a * a);
    return 0;
}

then I get those errors.

Derek, I thought that by including the BigIntegerLibrary.hh file, that the compiler would go through and compile all the necessary files that it will use.

How should I try and compile the program above in order to resolve the linking errors?

Upvotes: 29

Views: 89384

Answers (15)

adum
adum

Reputation: 2920

I have had a lot of success using the LibTomCrypt library for my crypto needs. It's fast, lean, and portable. It can do your RSA for you, or just handle the math if you want.

Upvotes: 2

Thomas Pornin
Thomas Pornin

Reputation: 74502

There is more to secure RSA implementation than just big numbers. A simple RSA implementation tends to leak private information through side channels, especially timing (in simple words: computation time depends on the processed data, which allows an attacker to recover some, possibly all, of the private key bits). Good RSA implementations implement countermeasures.

Also, beyond the modular exponentiation, there is the whole padding business, which is not conceptually hard, but, as all I/O and parsing code, has room for subtle bugs. The easiest code to write is the code which has already been written by somebody else.

Another point is that once you have your RSA code up and running, you may begin to envision extensions and other situations, e.g. "what if the private key I want to use is not in RAM but in a smartcard ?". Some existing RSA implementations are actually API which can handle that. In the Microsoft world, you want to lookup CryptoAPI, which is integrated in Windows. You may also want to look at NSS, which is what the Firefox browser uses for SSL.

To sum up: you can build up a RSA-compliant implementation from big integers, but this is more difficult to do correctly than what it usually seems, so my advice is to use an existing RSA implementation.

Upvotes: 3

Vlad
Vlad

Reputation: 31

Here is my approach, it combines fast exponentation using squaring + modular exponentation which reduces the space required.

long long mod_exp (long long n, long long e, long long mod)
{
  if(e == 1)
  {
       return (n % mod);
  }
  else
  {
      if((e % 2) == 1)
      {
          long long temp = mod_exp(n, (e-1)/2, mod);
          return ((n * temp * temp) % mod);
      }
      else
      {
          long long temp = mod_exp(n, e/2, mod);
          return ((temp*temp) % mod); 
      }
  }
}

Upvotes: 3

Vaibhav Bajpai
Vaibhav Bajpai

Reputation: 16814

I used GMP when I wrote the RSA implementation.

Upvotes: 0

robottobor
robottobor

Reputation: 11772

Openssl also has a Bignum type you can use. I've used it and it works well. Easy to wrap in an oo language like C++ or objective-C, if you want.

https://www.openssl.org/docs/crypto/bn.html

Also, in case you didn't know, to find the answer to the equation of this form x^y % z, look up an algorithm called modular exponentiation. Most crypto or bignum libraries will have a function specifically for this computation.

Upvotes: 2

tfinniga
tfinniga

Reputation: 6859

If you're not implementing RSA as a school assignment or something, then I'd suggest looking at the crypto++ library http://www.cryptopp.com

It's just so easy to implement crypto stuff badly.

Upvotes: 3

Derek Park
Derek Park

Reputation: 46856

Tomek, it sounds like you aren't linking to the BigInteger code correctly. I think you should resolve this problem rather than looking for a new library. I took a look at the source, and BigInteger::BigInteger(int) is most definitely defined. A brief glance indicates that the others are as well.

The link errors you're getting imply that you are either neglecting to compile the BigInteger source, or neglecting to include the resulting object files when you link. Please note that the BigInteger source uses the "cc" extension rather than "cpp", so make sure you are compiling these files as well.

Upvotes: 14

Maciej Hehl
Maciej Hehl

Reputation: 7995

The fact, that you have a problem using some biginteger library doesn't mean, that it's a bad approach.

Using long long is definitely a bad approach.

As others said already using a biginteger library is probably a good approach, but You have to post more detail on haw you use mentioned library for us to be able to help You resolve those errors.

Upvotes: 0

ConcernedOfTunbridgeWells
ConcernedOfTunbridgeWells

Reputation: 66702

For RSA you need a bignum library. The numbers are way too big to fit into a 64-bit long long. I once had a colleague at university who got an assignment to implement RSA including building his own bignum library.

As it happens, Python has a bignum library. Writing bignum handlers is small enough to fit into a computer science assignment, but still has enough gotchas to make it a non-trivial task. His solution was to use the Python library to generate test data to validate his bignum library.

You should be able to get other bignum libraries.

Alternatively, try implementing a prototype in Python and see if it's fast enough.

Upvotes: 3

David Ameller
David Ameller

Reputation: 1814

Just to note: __int64 and long long are non-standard extensions. Neither one is guaranteed to be supported by all C++ compilers. C++ is based on C89 (it came out in 98, so it couldn't be based on C99)

(C has support for 'long long' since C99)

By the way, I don't think that 64bit integers solve this problem.

Upvotes: 1

TFKyle
TFKyle

Reputation: 864

I'd suggest using gmp, it can handle arbitrarily long ints and has decent C++ bindings.

afaik on current hardware/sofware long longs are 64bit, so unsigned can handle numbers up to (2**64)-1 == 18446744073709551615 which is quite a bit smaller than numbers you'd have to deal with with RSA.

Upvotes: 13

Greg Hewgill
Greg Hewgill

Reputation: 994531

I would try out the GMP library - it is robust, well tested, and commonly used for this type of code.

Upvotes: 3

Scott Langham
Scott Langham

Reputation: 60411

Check out your compiler documentation. Some compilers have types defined such as __int64 that give you their size. Maybe you've got some of them available.

Upvotes: 1

Paige Ruten
Paige Ruten

Reputation: 176803

To see the size of a long long try this:

#include <stdio.h>

int main(void) {
    printf("%d\n", sizeof(long long));

    return 0;
}

On my machine it returns 8 which means 8 bytes which can store 2^64 values.

Upvotes: 3

Adam Pierce
Adam Pierce

Reputation: 34375

A long int is typically 64 bits which would probably not be enough to handle an integer that large. You'll probably need a bigint library of some kind.

See also this question on Stack Overflow

Upvotes: 1

Related Questions