2

I've been doing some research on the RSA encryption system, it's pretty simple to code one using small primes, as there aren't too many possibilities and performance is not a real issue.

Here's how RSA Works:

  • First, you generate a n value, product from 2 primes picked up randomly:

    n = p * q
    
    • Then you need your public key, called e. It can be any number coprime to φ(n):

      mcd(φ(n), e) = 1

    • According to the Euler function, φ(n) = (p-1)(q-1)

    • You still need your private key, known as d, which is the inverse of e on modulo **φ(n).

    • So d * e = 1 (mod φ(n))

    • n and e are your public values, when d is your private key. Nobody should know p or q, as with those values it would be possible to get φ(n), and use it to calculate d.
  • To encrypt a message, we use M = m^e (mod n), where m is the original message, and M is the encrypted one. So, everybody can send you an encrypted message you can read, by using your public values.
  • To decrypt a message, you use d, as it's the inverse of e, so M^d = (m^e)^d = m (mod n). The message can be decrypted, but only using d.

Knowing this, to encrypt a message we just need to get two random primes, calculate n, e, d, and make our encryption and decryption methods.


This seems pretty easy in theory, now let's turn this into java code:

I first choose two random primes, the bigger the number, the stronger the encryption. So I'll choose p = 1644623 and q = 1644751. According to this page, they are primes.

BigInteger p = new BigInteger("1644623");
BigInteger q = new BigInteger("1644751");

Then, on my init method, I initialize n, e and d:

BigInteger p = new BigInteger("1644623");
BigInteger q = new BigInteger("1644751");

BigInteger n;
BigInteger e;
BigInteger d;

void init() {
    n = p.multiply(q);

    BigInteger pn = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));

    e = n.subtract(pn);
    while (!mcd(pn, e).equals(BigInteger.ONE)) {
        e = e.add(BigInteger.ONE);
        System.out.println(e);
    }

    d = e.modPow(new BigInteger("-1"), pn);
}

I used BigInteger instead of long, as the values used are extremely big.

In theory, everything works. Practically, pn = 2704992034500, so checking if mcd(pn, e) = 1, and if not adding 1 to e and trying again it's not an option. This program is running since 30 minutes, at an average of 150.000 numbers / second. e = 548151505 and still not found mcd(pn, e) = 1.


Is there any way to find e in a reasonable time?


user207421
  • 305,947
  • 44
  • 307
  • 483
Juanco
  • 33
  • 1
  • 6
  • Isn't that what the Extended Euclidean Algorithm does? https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm – Thilo Feb 03 '16 at 00:08
  • There is no such thing as `mcd`. Perhaps you made a typo, because it's the `gcd` or Euclidean Algorithm. – Artjom B. Feb 03 '16 at 00:26
  • 2
    That's for getting the private key (d) from the public one (e), which is the next step and can be done just by d (mod n) = e^-1. What I'm trying to do is to generate e, the public key. – Juanco Feb 03 '16 at 00:27
  • @ArtjomB it's the absolutely same, only that in my country it's known as mcd (maximo comun divisor), which is the spanish translation of gcd (greatest common divisor). – Juanco Feb 03 '16 at 00:28
  • 1
    As user448810 answered, you don't need to find *e*, you just set it to some common value. If you're really interested in finding a "unique" *e*, then this question is probably better suited for [math.se] or [crypto.se]. Please check if there is already a similar question asked. There is a reason why Fermat Primes are chosen as *e* and that is the number of set bits must be low for fast encryption and fast signature verification. – Artjom B. Feb 03 '16 at 00:33
  • @Thilo No, it isn't. – Artjom B. Feb 03 '16 at 00:36
  • @Juanco: Can you show us the implementation of `mcd`? – Mark Dickinson Feb 03 '16 at 08:30

1 Answers1

2

Any prime number will be co-prime to the modulus, by definition, so you don't need to search for one, just pick a prime number. Since the encryption key is public, most RSA implementations use something that makes it easy to compute the modular exponentiation: 3 and 65537 = 2 ** 16 + 1 are both prime, and both are commonly used for the encryption key.

user448810
  • 17,381
  • 4
  • 34
  • 59
  • Common choices are [Fermat numbers](https://en.wikipedia.org/wiki/Fermat_number). Also, 3 is a very bad choice if textbook RSA is used. – Artjom B. Feb 03 '16 at 00:29
  • @ArtjomB.: But in that case, using 3 isn't the problem. The problem is textbook RSA. – user2357112 Feb 03 '16 at 01:08
  • 2
    "Any prime number will be co-prime to the modulus, by definition". This isn't true: a small prime number could easily be a divisor of `phi(n)`. In the example that the OP gave, `phi(n)` is divisible by 3, so using `e = 3` isn't an option, for example. If you're going to always use `3`, you then need to make some extra effort to make sure that neither of your chosen primes is congruent to 1 modulo `3`. Similarly if you decide in advance that you want to use `e = 65537`. – Mark Dickinson Feb 03 '16 at 08:21
  • @MarkDickinson: In other words, what's important for the exponents is co-primality to `phi(n)`, *not* co-primality to `n`. – President James K. Polk Feb 03 '16 at 22:13
  • @JamesKPolk: Ah, good point; my too-quick reading failed to notice the "co-prime to *the modulus*" bit. So I take it back: the statement I quoted *is* true (assuming you don't pick p or q itself), but not terribly helpful. – Mark Dickinson Feb 04 '16 at 06:42