Open In App

How to generate Large Prime numbers for RSA Algorithm

The security of the RSA algorithm is based on the difficulty of factorizing very large numbers. The setup of an RSA cryptosystem involves the generation of two large primes, say p and q, from which, the RSA modulus is calculated as n = p * q. The greater the modulus size, the higher is the security level of the RSA system. The recommended RSA modulus size for most settings is 2048 bits to 4096 bits. Thus, the primes to be generated need to be 1024 bit to 2048 bit long. For the synthesis of such large primes, instead of depending on deterministic methods, we rely on finding numbers that are prime with a satisfactorily high level of probability.

Large Prime Generation Procedure:

Fig 1: Steps involved in Generation of Large Primes for RSA

Below are the steps to implement the above procedure:

1. Picking a Random Prime Candidate 

#include <bits/stdc++.h>
using namespace std;
 
long nBitRandom(int n)
{
    // Returns a random number
    // between 2**(n-1)+1 and 2**n-1'''
    long max = (long)powl(2, n) - 1;
    long min = (long)powl(2, n - 1) + 1;
    return min + (rand() % ( max - min + 1 ) );
}
 
// This code is contributed by phasing17.

                    
import java.util.concurrent.ThreadLocalRandom;
 
class GFG
{
  static long nBitRandom(int n)
  {
    // Returns a random number
    // between 2**(n-1)+1 and 2**n-1'''
    int max = (int)Math.pow(2, n) - 1;
    int min = (int)Math.pow(2, n - 1) + 1;
    return ThreadLocalRandom.current().nextInt(min, max + 1);
  }
}
 
// This code is contributed by phasing17.

                    
def nBitRandom(n):
   
    # Returns a random number
    # between 2**(n-1)+1 and 2**n-1'''
    return(random.randrange(2**(n-1)+1, 2**n-1))

                    
using System;
using System.Collections.Generic;
 
class GFG
{
    static long nBitRandom(int n)
    {
        var rand = new Random();
         
        // Returns a random number
        // between 2**(n-1)+1 and 2**n-1'''
        int max = (int)Math.Pow(2, n) - 1;
        int min = (int)Math.Pow(2, n - 1) + 1;
        return rand.Next(min, max + 1);
    }
     
}
 
// This code is contributed by phasing17.

                    
function nBitRandom(n)
{
    // Returns a random number
    // between 2**(n-1)+1 and 2**n-1'''
    let max =  2**n-1
    let min = 2**(n-1)+1
    return Math.floor(Math.random() * (max - min) + min)
}
 
// This code is contributed by phasing17.

                    

2. Division with First Primes (Low-Level Primality Test) 

// C++ Program to implement the approach
int getLowLevelPrime(int n)
{
   
    // Generate a prime candidate divisible
    // by first primes
   
    //  Repeat until a number satisfying
    //  the test isn't found
    while (true)
    {
        //  Obtain a random number
        int prime_candidate = nBitRandom(n) 
   
        for (int divisor : first_primes_list)
        {
            if (prime_candidate % divisor == 0
            && divisor**2 <= prime_candidate)
                break
            //  If no divisor found, return value
            else
                return prime_candidate 
        }
    }
}
 
// This code is contributed by phasing17.

                    
static int getLowLevelPrime(int n)
{
 
  // Generate a prime candidate divisible
  // by first primes
 
  //  Repeat until a number satisfying
  //  the test isn't found
  while (true) {
    //  Obtain a random number
    int prime_candidate = nBitRandom(n);
 
    for (int divisor : first_primes_list)
    {
      if (prime_candidate % divisor == 0
          && divisor * divisor <= prime_candidate)
        break;
      //  If no divisor found, return value
      else
        return prime_candidate;
    }
  }
}
 
// This code is contributed by phasing17.

                    
def getLowLevelPrime(n):
    '''Generate a prime candidate divisible
      by first primes'''
   
    # Repeat until a number satisfying
    # the test isn't found
    while True
   
        # Obtain a random number
        prime_candidate = nBitRandom(n) 
   
        for divisor in first_primes_list: 
            if prime_candidate % divisor == 0
            and divisor**2 <= prime_candidate:
                break
            # If no divisor found, return value
            else: return prime_candidate

                    
static int getLowLevelPrime(int n)
{
 
    // Generate a prime candidate divisible
    // by first primes
 
    //  Repeat until a number satisfying
    //  the test isn't found
    while (true) {
        //  Obtain a random number
        int prime_candidate = nBitRandom(n);
 
        foreach(int divisor in first_primes_list)
        {
            if (prime_candidate % divisor == 0
                && divisor * divisor <= prime_candidate)
                break;
            //  If no divisor found, return value
            else
                return prime_candidate;
        }
    }
}
 
// This code is contributed by phasing17.

                    
function getLowLevelPrime(n)
{
    // Generate a prime candidate divisible
    // by first primes
   
    //  Repeat until a number satisfying
    //  the test isn't found
    while (true)
    {
        //  Obtain a random number
        prime_candidate = nBitRandom(n) 
   
        for (let divisor of first_primes_list)
        {
            if (prime_candidate % divisor == 0
            && divisor**2 <= prime_candidate)
                break
            //  If no divisor found, return value
            else
                return prime_candidate 
        }
    }
}
 
// This code is contributed by phasing17.

                    

3. Rabin Miller Primality Test (High-Level Primality Test) 

// This function calculates (base ^ exp) % mod
int expmod(int base, int exp, int mod ){
  if (exp == 0) return 1;
  if (exp % 2 == 0){
    return (int)pow( expmod( base, (exp / 2), mod), 2) % mod;
  }
  else {
    return (base * expmod( base, (exp - 1), mod)) % mod;
  }
}
 
bool trialComposite(int round_tester, int evenComponent, int miller_rabin_candidate, int maxDivisionsByTwo)
{
  if (expmod(round_tester, evenComponent, miller_rabin_candidate) == 1 )
    return false;
  for (int i = 0; i < maxDivisionsByTwo; i++)
  {
    if (expmod(round_tester, (1 << i) * evenComponent, miller_rabin_candidate) == miller_rabin_candidate - 1)
      return false;
  }
  return true;
}
 
bool isMillerRabinPassed(int miller_rabin_candidate)
{
  // Run 20 iterations of Rabin Miller Primality test
 
  int maxDivisionsByTwo = 0;
  int evenComponent = miller_rabin_candidate-1;
 
  while (evenComponent % 2 == 0)
  {
    evenComponent >>= 1;
    maxDivisionsByTwo += 1;
  }
 
  // Set number of trials here
  int numberOfRabinTrials = 20;
  for (int i = 0; i < (numberOfRabinTrials) ; i++)
  {
    int round_tester = rand() * (miller_rabin_candidate - 2) + 2;
 
    if (trialComposite(round_tester, evenComponent, miller_rabin_candidate, maxDivisionsByTwo))
      return false;
  }
  return true;
}
 
// This code is contributed by phasing17.

                    
import java.util.concurrent.ThreadLocalRandom;
 
// This function calculates (base ^ exp) % mod
static int expmod(int base, int exp, int mod ){
  if (exp == 0) return 1;
  if (exp % 2 == 0){
    return (int)Math.pow( expmod( base, (exp / 2), mod), 2) % mod;
  }
  else {
    return (base * expmod( base, (exp - 1), mod)) % mod;
  }
}
 
static bool trialComposite(int round_tester, int evenComponent,
                           int miller_rabin_candidate, int maxDivisionsByTwo)
{
  if (expmod(round_tester, evenComponent, miller_rabin_candidate) == 1 )
    return false;
  for (int i = 0; i < maxDivisionsByTwo; i++)
  {
    if (expmod(round_tester, (1 << i) * evenComponent,
               miller_rabin_candidate) == miller_rabin_candidate - 1)
      return false;
  }
  return true;
}
 
static bool isMillerRabinPassed(int miller_rabin_candidate)
{
  // Run 20 iterations of Rabin Miller Primality test
 
  int maxDivisionsByTwo = 0;
  int evenComponent = miller_rabin_candidate-1;
 
  while (evenComponent % 2 == 0)
  {
    evenComponent >>= 1;
    maxDivisionsByTwo += 1;
  }
 
  // Set number of trials here
  int numberOfRabinTrials = 20;
  for (int i = 0; i < (numberOfRabinTrials) ; i++)
  {
    int round_tester = ThreadLocalRandom.current().nextInt(2, miller_rabin_candidate + 1);
 
    if (trialComposite(round_tester, evenComponent,
                       miller_rabin_candidate, maxDivisionsByTwo))
      return false;
  }
  return true;
}
 
// This code is contributed by phasing17.

                    
def isMillerRabinPassed(miller_rabin_candidate):
    '''Run 20 iterations of Rabin Miller Primality test'''
   
    maxDivisionsByTwo = 0
    evenComponent = miller_rabin_candidate-1
   
    while evenComponent % 2 == 0:
        evenComponent >>= 1
        maxDivisionsByTwo += 1
    assert(2**maxDivisionsByTwo * evenComponent == miller_rabin_candidate-1)
   
    def trialComposite(round_tester):
        if pow(round_tester, evenComponent, 
               miller_rabin_candidate) == 1:
            return False
        for i in range(maxDivisionsByTwo):
            if pow(round_tester, 2**i * evenComponent,
                   miller_rabin_candidate) 
            == miller_rabin_candidate-1:
                return False
        return True
   
    # Set number of trials here
    numberOfRabinTrials = 20
    for i in range(numberOfRabinTrials):
        round_tester = random.randrange(2,
                       miller_rabin_candidate)
        if trialComposite(round_tester):
            return False
    return True

                    
// This function calculates (base ^ exp) % mod
static int expmod(int base, int exp, int mod ){
  if (exp == 0) return 1;
  if (exp % 2 == 0){
    return (int)Math.Pow( expmod( base, (exp / 2), mod), 2) % mod;
  }
  else {
    return (base * expmod( base, (exp - 1), mod)) % mod;
  }
}
 
static bool trialComposite(int round_tester, int evenComponent,
                           int miller_rabin_candidate, int maxDivisionsByTwo)
{
  if (expmod(round_tester, evenComponent, miller_rabin_candidate) == 1 )
    return false;
  for (int i = 0; i < maxDivisionsByTwo; i++)
  {
    if (expmod(round_tester, (1 << i) * evenComponent,
               miller_rabin_candidate) == miller_rabin_candidate - 1)
      return false;
  }
  return true;
}
 
static bool isMillerRabinPassed(int miller_rabin_candidate)
{
  // Run 20 iterations of Rabin Miller Primality test
 
  int maxDivisionsByTwo = 0;
  int evenComponent = miller_rabin_candidate-1;
 
  while (evenComponent % 2 == 0)
  {
    evenComponent >>= 1;
    maxDivisionsByTwo += 1;
  }
 
  // Set number of trials here
  int numberOfRabinTrials = 20;
  for (int i = 0; i < (numberOfRabinTrials) ; i++)
  {
      Random rand = new Random();
    int round_tester = rand.Next(2, miller_rabin_candidate);
 
    if (trialComposite(round_tester, evenComponent,
                       miller_rabin_candidate, maxDivisionsByTwo))
      return false;
  }
  return true;
}
 
// This code is contributed by phasing17.

                    
// This function calculates (base ^ exp) % mod
 
function expmod( base, exp, mod ){
  if (exp == 0) return 1;
  if (exp % 2 == 0){
    return Math.pow( expmod( base, (exp / 2), mod), 2) % mod;
  }
  else {
    return (base * expmod( base, (exp - 1), mod)) % mod;
  }
}
 
function isMillerRabinPassed(miller_rabin_candidate)
{
    // Run 20 iterations of Rabin Miller Primality test
   
    let maxDivisionsByTwo = 0
    let evenComponent = miller_rabin_candidate-1
   
    while (evenComponent % 2 == 0)
    {
        evenComponent >>= 1
        maxDivisionsByTwo += 1
    }
 
    function trialComposite(round_tester)
    {
        if (expmod(round_tester, evenComponent, 
               miller_rabin_candidate) == 1 )
            return false
        for (var i = 0; i < (maxDivisionsByTwo); i++)
        {
            if (expmod(round_tester, 2**i * evenComponent,
                   miller_rabin_candidate) 
            == miller_rabin_candidate-1)
                return false
        }
        return true
    }
     
    // Set number of trials here
    let numberOfRabinTrials = 20
    for (var i = 0; i < (numberOfRabinTrials) ; i++)
    {
        let round_tester = Math.random() * (miller_rabin_candidate - 2) + 2;
         
        if (trialComposite(round_tester))
            return false
    }
    return true
}

                    

4. Combining the above steps to generate the code 

Below is the complete implementation of the above approach 

# Large Prime Generation for RSA
import random
 
# Pre generated primes
first_primes_list = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
                     31, 37, 41, 43, 47, 53, 59, 61, 67,
                     71, 73, 79, 83, 89, 97, 101, 103,
                     107, 109, 113, 127, 131, 137, 139,
                     149, 151, 157, 163, 167, 173, 179,
                     181, 191, 193, 197, 199, 211, 223,
                     227, 229, 233, 239, 241, 251, 257,
                     263, 269, 271, 277, 281, 283, 293,
                     307, 311, 313, 317, 331, 337, 347, 349]
 
 
def nBitRandom(n):
    return random.randrange(2**(n-1)+1, 2**n - 1)
 
 
def getLowLevelPrime(n):
    '''Generate a prime candidate divisible
    by first primes'''
    while True:
        # Obtain a random number
        pc = nBitRandom(n)
 
        # Test divisibility by pre-generated
        # primes
        for divisor in first_primes_list:
            if pc % divisor == 0 and divisor**2 <= pc:
                break
        else:
            return pc
 
 
def isMillerRabinPassed(mrc):
    '''Run 20 iterations of Rabin Miller Primality test'''
    maxDivisionsByTwo = 0
    ec = mrc-1
    while ec % 2 == 0:
        ec >>= 1
        maxDivisionsByTwo += 1
    assert(2**maxDivisionsByTwo * ec == mrc-1)
 
    def trialComposite(round_tester):
        if pow(round_tester, ec, mrc) == 1:
            return False
        for i in range(maxDivisionsByTwo):
            if pow(round_tester, 2**i * ec, mrc) == mrc-1:
                return False
        return True
 
    # Set number of trials here
    numberOfRabinTrials = 20
    for i in range(numberOfRabinTrials):
        round_tester = random.randrange(2, mrc)
        if trialComposite(round_tester):
            return False
    return True
 
 
if __name__ == '__main__':
    while True:
        n = 1024
        prime_candidate = getLowLevelPrime(n)
        if not isMillerRabinPassed(prime_candidate):
            continue
        else:
            print(n, "bit prime is: \n", prime_candidate)
            break

                    
// 64 bits is maximum you can get in c++ so it's implemented to do so
// you can edit constexpr var in getRandom64() to get lower amount of bits
#include <iostream>
#include <cstdint>
#include <vector>
#include <random>
#include <bitset>
 
uint64_t mulmod(uint64_t a, uint64_t b, uint64_t m) {
    int64_t res = 0;
  
    while (a != 0) {
        if (a & 1) {
 
            res = (res + b) % m;
        }
        a >>= 1;
        b = (b << 1) % m;
    }
    return res;
}
 
uint64_t powMod(uint64_t a, uint64_t b, uint64_t n) {
    uint64_t x = 1;
     
    a %= n;
 
    while (b > 0) {
        if (b % 2 == 1) {
            x = mulmod(x, a, n); // multiplying with base
        }
        a = mulmod(a, a, n); // squaring the base
        b >>= 1;
    }
    return x % n;
}
 
std::vector<int> first_primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
                                    31, 37, 41, 43, 47, 53, 59, 61, 67,
                                    71, 73, 79, 83, 89, 97, 101, 103,
                                    107, 109, 113, 127, 131, 137, 139,
                                    149, 151, 157, 163, 167, 173, 179,
                                    181, 191, 193, 197, 199, 211, 223,
                                    227, 229, 233, 239, 241, 251, 257,
                                    263, 269, 271, 277, 281, 283, 293,
                                    307, 311, 313, 317, 331, 337, 347, 349 };
 
// going through all 64 bits and placing randomly 0s and 1s
// setting first and last bit to 1 to get 64 odd number
uint64_t getRandom64() {
    // the value need to be 63 bits because you can not using 64 bit values do a^2 which is needed
    constexpr int bits = 63;
    std::bitset<bits> a;
 
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<short> distr(0, 1);
 
    for (int i = 0; i < bits; i++) {
        a[i] = distr(gen);
    }
 
    a[0] = 1;
    a[bits - 1] = 1;
 
    return a.to_ullong();
}
 
uint64_t getLowLevelPrime() {
    while (true) {
        uint64_t candidate = getRandom64();
        bool is_prime = true;
        for (int i = 0; i < first_primes.size(); i++) {
            if (candidate == first_primes[i])
                return candidate;
 
            if (candidate % first_primes[i] == 0) {
                is_prime = false;
                break;
            }
        }
        if (is_prime)
            return candidate;
    }
}
 
bool trialComposite(uint64_t a, uint64_t evenC, uint64_t to_test, int max_div_2) {
    if (powMod(a, evenC, to_test) == 1)
        return false;
 
    for (int i = 0; i < max_div_2; i++) {
        uint64_t temp = static_cast<uint64_t>(1) << i;
        if (powMod(a, temp * evenC, to_test) == to_test - 1)
            return false;
    }
 
    return true;
}
 
bool MillerRabinTest(uint64_t to_test) {
    constexpr int accuracy = 20;
 
    int max_div_2 = 0;
    uint64_t evenC = to_test - 1;
    while (evenC % 2 == 0) {
        evenC >>= 1;
        max_div_2++;
    }
 
    // random numbers init
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<uint64_t> distr(2, to_test);
 
    for (int i = 0; i < accuracy; i++) {
        uint64_t a = distr(gen);
 
        if (trialComposite(a, evenC, to_test, max_div_2)) {
            return false;
        }
    }
 
    return true;
}
 
uint64_t getBigPrime() {
    while (true) {
        uint64_t candidate = getLowLevelPrime();
        if (MillerRabinTest(candidate))
            return candidate;
    }
}
 
int main(){
     std::cout<<getBigPrime()<<std::endl;
}

                    

Output
1024 bit prime is: 
 170154366828665079503315635359566390626153860097410117673698414542663355444709893966571750073322692712277666971313348160841835991041384679700511912064982526249529596585220499141442747333138443745082395711957231040341599508490720584345044145678716964326909852653412051765274781142172235546768485104821112642811

Note: Library Generation of Large Primes in Python

The pycrypto library is a comprehensive collection of secure hash functions and various encryption algorithms. It also includes basic functions commonly required in encryption/decryption setups such as random number generation and random prime number generation. The goal of generating a random prime number with a specified bit-size can be achieved using the pycrypto getPrime module. 
The syntax for generating a random n-bit prime number is:

from Crypto.Util import number
number.getPrime(n)

                    

Article Tags :