diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0548357 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..c4b47e0 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/RSA.iml b/RSA.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/RSA.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..75ded5b --- /dev/null +++ b/src/Main.java @@ -0,0 +1,9 @@ +import java.math.BigInteger; + +public class Main { + public static void main(String[] args) { + BigInteger prime = Prime.generate(32); + System.out.println("Finished - number is "+prime); + + } +} diff --git a/src/Prime.java b/src/Prime.java new file mode 100644 index 0000000..8ddf1d6 --- /dev/null +++ b/src/Prime.java @@ -0,0 +1,132 @@ +import java.math.BigInteger; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +public class Prime { + /** + * Calculates the integer square root of a number. + * Source: https://stackoverflow.com/questions/4407839/how-can-i-find-the-square-root-of-a-java-biginteger/13023513#13023513 + * + * @param x the number + * @return the square root + */ + private static BigInteger sqrt(BigInteger x) { + BigInteger div = BigInteger.ZERO.setBit(x.bitLength()/2); + BigInteger div2 = div; + // Loop until we hit the same value twice in a row, or wind + // up alternating. + for(;;) { + BigInteger y = div.add(x.divide(div)).shiftRight(1); + if (y.equals(div) || y.equals(div2)) + return y; + div2 = div; + div = y; + } + } + + /** + * Checks, whether a number is a prime or not. Uses naive implementation accelerated by multithreading. + * + * @param candidate the number to check + * @return the boolean + */ + private static boolean isPrime(BigInteger candidate) { + // Check special candidate values 0, 1, 2 and even + if (candidate.compareTo(BigInteger.ZERO) == 0 // candidate == 0 + || candidate.compareTo(BigInteger.ONE) == 0) { // candidate == 1) + return false; + } + if (candidate.compareTo(BigInteger.valueOf(2)) == 0) { // candidate == 2 + return true; + } else if (candidate.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) { // candidate is even + return false; + } + + // Divide interval into segments, one for each cpu core + int cores = Runtime.getRuntime().availableProcessors(); + + BigInteger max = sqrt(candidate).add(BigInteger.ONE); + BigInteger min = BigInteger.valueOf(3); + BigInteger step = max.subtract(min).divide(BigInteger.valueOf(cores)); + BigInteger remainder = max.subtract(min).mod(BigInteger.valueOf(cores)); + + int i = 0; + List workers = new LinkedList<>(); + while (i < cores) { + BigInteger num = step; + if (remainder.compareTo(BigInteger.ZERO) == 1) { // remainder > 0 + num = num.add(BigInteger.ONE); + remainder = remainder.subtract(BigInteger.ONE); + } + num = num.subtract(BigInteger.ONE); + if (num.compareTo(BigInteger.ZERO) >= 0) { + workers.add(new Worker(candidate, min, min.add(num), "Thread " + i)); + workers.get(i).start(); + min = min.add(num).add(BigInteger.ONE); + } + + i++; + if (min.compareTo(max) > 0) { + break; + } + } + // Wait for workers to complete + boolean stop = false; + boolean isPrime = true; + + while (!stop) { + i = 0; + while (i < workers.size()) { + Worker w = workers.get(i); + try { + w.join(500); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + if (w.hasFinished()) { + if (!w.isPrime()) { + isPrime = false; + stop = true; + break; + } else { + // This worker is done, remove it from the list + workers.remove(w); + if (workers.isEmpty()) { + stop = true; + break; + } + } + } + i++; + } + } + + // Stop workers + for (Worker w: workers) { + w.interrupt(); + } + + return isPrime; + } + + + /** + * Generates a guaranteed prime of the given length. + * + * @param bits binary length of the prime to generate + * @return prime number + */ + public static BigInteger generate(int bits) { + Random rng = new Random(); + BigInteger candidate = new BigInteger(bits, rng); + int i = 0; + while (!isPrime(candidate)){ + //System.out.println("Not a prime: " + candidate); + candidate = new BigInteger(bits, rng); + i++; + } + //System.out.println("Found prime after " + i + " tries: " + candidate); + return candidate; + } +} diff --git a/src/RSA.java b/src/RSA.java new file mode 100644 index 0000000..0253b12 --- /dev/null +++ b/src/RSA.java @@ -0,0 +1,28 @@ +public class RSA { +// p = 5, q = 11 +// RSA-Modul N = p * q = 55 +// Phi(N) = Phi(p)*Phi(q) | weil eigenschaft eulersche phi funktion und p,q teilerfremd +// = (p-1)*(q-1) | p,q primzahlen, daher nur durch 1 und sich selbst teilbar und alle anderen teilerfremd +// = 4*10 = 40 +// e: 1 < e < Phi(N) und ggT(e, Phi(N)) = 1 +// e elem aus {3,..} => e = 3 +// (e,N) = (3, 55) public key +// ----- +// d: e*d kongr 1 mod Phi(N) => e*d mod Phi(N) = 1 +// 3*d mod 40 = 1 +// Durch probieren: d=27 => (27, 55) private key +// +// ---- +// Verschlüsseln +// 13 +// c = m^e (mod N) => 13^3 (mod 55) = 52 = c +// ---- +// Entschlüsseln +// m = c^d (mod N) => 52^27 (mod 55) = 13 = m + public RSA() { + + } + + + +} diff --git a/src/Worker.java b/src/Worker.java new file mode 100644 index 0000000..e6722c7 --- /dev/null +++ b/src/Worker.java @@ -0,0 +1,58 @@ +import java.math.BigInteger; + +/** + * Worker class used in multithreading to check, whether a given number is a prime. + */ +public class Worker extends Thread { + private boolean isPrime; + private BigInteger minVal; + private BigInteger maxVal; + private BigInteger candidate; + private boolean finished = false; + private String threadName ; + + public Worker(BigInteger candidate, BigInteger min, BigInteger max, String threadName) { + this.minVal = min; + this.maxVal = max; + this.candidate = candidate; + this.isPrime = true; + this.threadName = threadName; + //System.out.println("Created "+threadName+" for "+min+"-"+max+""); + } + + /** + * Returns a flag, indicating whether the prime candidate has a divisor in the given interval. + * Since the thread might be still be running, it is important to check it first by using the + * hasFinished() method. + * + * @return flag indicating whether there is a divisor or not + */ + public boolean isPrime() { + return this.isPrime; + } + + /** + * Returns if the thread has finished checking the given interval. + * + * @return the boolean + */ + public boolean hasFinished() { return this.finished; } + + public void run() { + BigInteger divCandidate = minVal; + if (divCandidate.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)){ + divCandidate = divCandidate.add(BigInteger.ONE); + } + while (divCandidate.compareTo(maxVal) < 1){ //divCandidate <= maxVal + //System.out.println(this.threadName + " is testing "+divCandidate); + if (candidate.mod(divCandidate).equals(BigInteger.ZERO)) { + this.isPrime = false; + this.finished = true; + return; + } + divCandidate = divCandidate.add(BigInteger.ONE).add(BigInteger.ONE); + } + this.finished = true; + // No divisor found, we are done for this interval + } +}