Skip to content

Instantly share code, notes, and snippets.

@stephnr
Last active January 2, 2016 04:48
Show Gist options
  • Save stephnr/8252475 to your computer and use it in GitHub Desktop.
Save stephnr/8252475 to your computer and use it in GitHub Desktop.
RSA key generator written in Java. Implements the eratosthenes sieve for computing prime numbers. Keys are based from a selection of 5000 prime numbers. Estimated run time efficiency: [ Roughly ~ 0.8 seconds ]
import java.util.Random;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.math.BigInteger;
class RSA {
private int[] public_Key = new int[2];
private int[] privat_Key = new int[2];
public static void main(String[] args) {
RSA keys = new RSA();
int[] pubK = keys.getPublicKey();
int[] privK = keys.getPrivateKey();
for(int i : pubK) {
System.out.println("Public Key: " + i);
}
for(int i : privK) {
System.out.println("Private Key: " + i);
}
}
public RSA() {
generate_Keys(5000);
}
public int[] getPublicKey() {
return this.public_Key;
}
public int[] getPrivateKey() {
return this.privat_Key;
}
private void generate_Keys(int complexity) {
ArrayList<Integer> primeTable = eratosthenes_Sieve(complexity);
Random rn = new Random();
int prime1 = primeTable.get(rn.nextInt(primeTable.size()));
int prime2 = primeTable.get(rn.nextInt(primeTable.size()));
//System.out.println("Primes: " + prime1 + " " + prime2);
int n = prime1 * prime2;
//System.out.println("N: " + n);
int prodP = (prime1 - 1) * (prime2 - 1);
//System.out.println("prodP: " + prodP);
ArrayList<Integer> coprimes = new ArrayList<>();
for(int i = 0; i < primeTable.size(); i++) {
if(primeTable.get(i) >= prodP) break;
if(gcd(primeTable.get(i),prodP) == 1 && primeTable.get(i)%2 == 1) coprimes.add(primeTable.get(i));
}
int e = coprimes.get(rn.nextInt(coprimes.size()));
int[] pk = new int[4];
public_Key[0] = n;
public_Key[1] = e;
int[] result = extended_GCD(e, prodP);
int d = prodP + result[0];
privat_Key[0] = n;
privat_Key[1] = d;
}
private ArrayList<Integer> eratosthenes_Sieve(int num_Of_Primes) {
int limit = num_Of_Primes;
num_Of_Primes *= 4.5;
int[] primeTable = new int[num_Of_Primes];
primeTable[0] = 1;
for( int i = 4; i < num_Of_Primes; i += 2) primeTable[i] = 1;
for( int i = 6; i < num_Of_Primes; i += 3) primeTable[i] = 1;
for( int i = 10; i < num_Of_Primes; i += 5) primeTable[i] = 1;
for( int i = 14; i < num_Of_Primes; i += 7) primeTable[i] = 1;
ArrayList<Integer> primes = new ArrayList<Integer>();
for(int i = 1; i < num_Of_Primes; i++) {
if(primeTable[i] == 0) primes.add(i);
if(primes.size() == limit) break;
}
return primes;
}
private int gcd(int a, int b) {
if(a == 0 || b == 0) return a + b;
return gcd(b, a%b);
}
private int[] extended_GCD(int a, int b) {
int[] result = {1,0};
if(b == 0) return result;
else {
int q = a/b;
int r = a - b*q;
result = extended_GCD(b,r);
int temp = result[0];
result[0] = result[1];
result[1] = temp - q * result[0];
return result;
}
}
// Given a string, returns an encrypted line
public String encrypt_Line(String text, int[] public_Key) {
String result = "";
for(int i = 0; i < text.length(); i++) {
int m = (int) text.charAt(i);
BigInteger encrypt = BigInteger.valueOf(m);
m = encrypt.pow(public_Key[1]).mod(BigInteger.valueOf(public_Key[0])).intValue();
result += String.valueOf(m) + " ";
}
return result;
}
// Given an encrypted string, returns the original string
public String decrypt_Line(String code, int[] privat_Key) {
String result = "";
StringTokenizer st = new StringTokenizer(code);
while(st.hasMoreTokens()) {
BigInteger base = BigInteger.valueOf(Integer.parseInt(st.nextToken()));
int temp = base.pow(privat_Key[1]).mod(BigInteger.valueOf(privat_Key[0])).intValue();
char ch = (char) temp;
result += ch;
}
return result;
}
// Performs encryption on an entire array of strings
public ArrayList<String> encrypt_Text(ArrayList<String> text, int[] public_Key) {
for(int i = 0; i < text.size(); i++) text.set(i, encrypt_Line(text.get(i).toString(), public_Key));
return text;
}
// Performs decryption on an entire array of encrypted strings
public ArrayList<String> decrypt_Text(ArrayList<String> text, int[] privat_Key) {
for(int i = 0; i < text.size(); i++) text.set(i, decrypt_Line(text.get(i).toString(), privat_Key));
return text;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment