From 41eeed22bb6bcd0ca99bd5555843f5c0d2a3cb94 Mon Sep 17 00:00:00 2001 From: akimmig Date: Wed, 28 Apr 2021 13:06:57 +0200 Subject: [PATCH] RSA --- Verschlüsselung/.classpath | 10 + Verschlüsselung/.gitignore | 1 + Verschlüsselung/.project | 17 + .../.settings/org.eclipse.jdt.core.prefs | 14 + Verschlüsselung/src/RSA/Main.java | 27 ++ Verschlüsselung/src/RSA/RSA.java | 450 ++++++++++++++++++ 6 files changed, 519 insertions(+) create mode 100644 Verschlüsselung/.classpath create mode 100644 Verschlüsselung/.gitignore create mode 100644 Verschlüsselung/.project create mode 100644 Verschlüsselung/.settings/org.eclipse.jdt.core.prefs create mode 100644 Verschlüsselung/src/RSA/Main.java create mode 100644 Verschlüsselung/src/RSA/RSA.java diff --git a/Verschlüsselung/.classpath b/Verschlüsselung/.classpath new file mode 100644 index 0000000..038a0e7 --- /dev/null +++ b/Verschlüsselung/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Verschlüsselung/.gitignore b/Verschlüsselung/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/Verschlüsselung/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Verschlüsselung/.project b/Verschlüsselung/.project new file mode 100644 index 0000000..4565c56 --- /dev/null +++ b/Verschlüsselung/.project @@ -0,0 +1,17 @@ + + + Verschlüsselung + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/Verschlüsselung/.settings/org.eclipse.jdt.core.prefs b/Verschlüsselung/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..ef28d2b --- /dev/null +++ b/Verschlüsselung/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,14 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=13 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=13 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=13 diff --git a/Verschlüsselung/src/RSA/Main.java b/Verschlüsselung/src/RSA/Main.java new file mode 100644 index 0000000..8c68d3b --- /dev/null +++ b/Verschlüsselung/src/RSA/Main.java @@ -0,0 +1,27 @@ +package RSA; + +public class Main { + public static void main(String[] args) throws Exception { + RSA r = new RSA(); + r.generatePair(1024); + + System.out.println(r); + + System.out.println(); + + String s = r.encrypt("35"); + + System.out.println(s); + System.out.println(r.decrypt(s)); + + System.out.println(); + System.out.println(); + + System.out.println(r.toPublicFileString()); + + System.out.println(); + + System.out.println(r.toPrivateFileString()); + } + +} diff --git a/Verschlüsselung/src/RSA/RSA.java b/Verschlüsselung/src/RSA/RSA.java new file mode 100644 index 0000000..160c5c8 --- /dev/null +++ b/Verschlüsselung/src/RSA/RSA.java @@ -0,0 +1,450 @@ +package RSA; + +import java.math.BigInteger; +import java.util.Base64; +import java.util.Random; + +/** + * @author Alexander Kimmig + */ +public class RSA { + /** + * first prime number + */ + private BigInteger p; + + /** + * second prime number + */ + private BigInteger q; + + /** + * modulus p*q + */ + private BigInteger N; + + /** + * euler phi-function + */ + private BigInteger phi; + + /** + * exponent for encryption + */ + private BigInteger e; + + /** + * exponent for decryption + */ + private BigInteger d; + + private static final BigInteger B0 = new BigInteger("0"); + private static final BigInteger B1 = new BigInteger("1"); + private static final BigInteger B2 = new BigInteger("2"); + + /** + * default constructor + */ + public RSA() { + this.p = null; + this.q = null; + this.N = null; + this.phi = null; + this.e = null; + this.d = null; + } + + /** + * constructor with setting prime numbers manually + * @param p first prime number + * @param q second prime number + * @param e exponent (coprime to phi) + * @throws Exception + */ + public RSA(String p, String q, String e) throws Exception { + this.p = new BigInteger(p); + this.q = new BigInteger(q); + this.N = this.p.multiply(this.q); + this.phi = this.p.subtract(B1).multiply(this.q.subtract(B1)); + this.e = new BigInteger(e); + this.d = this.findd(); + } + + /** + * auto-generate a public-private keypair with 1024 bits + * @throws Exception + */ + public void generatePair() throws Exception { this.generatePair(1024); } + + /** + * auto-generate a public-private keypair + * @param bits bitlength for prime numbers + * @param ebits bitlength for encryption exponent + * @throws Exception + */ + public void generatePair(int bits) throws Exception { + Random rand = new Random(); + int lengthp = (bits*(90+rand.nextInt(20))/200); + int lengthq = bits - lengthp; + + this.p = new BigInteger(RSA.generatePrime(lengthp)); + + while (this.N == null || this.N.bitLength() != bits) { + if (this.N != null && this.N.bitLength() < bits) lengthq++; + else if (this.N != null && this.N.bitLength() > bits) lengthq--; + + this.q = new BigInteger(RSA.generatePrime(lengthq)); + this.N = this.p.multiply(this.q); + } + this.phi = this.p.subtract(B1).multiply(this.q.subtract(B1)); + this.e = new BigInteger("65537"); + this.d = this.findd(); + } + + /** + * manually set private key + * @param d exponent for decryption + * @param N RSA modulus + */ + public void setPrivate(String d, String N) { + this.d = new BigInteger(d); + this.N = new BigInteger(N); + } + + /** + * manually set public key + * @param d exponent for encryption + * @param N RSA modulus + */ + public void setPublic(String e, String N) { + this.e = new BigInteger(e); + this.N = new BigInteger(N); + } + + /** + * helper-class for return-values for extended euclidean algorithm + * @author Alexander Kimmig + */ + private static class eeareturn { + BigInteger s; + BigInteger t; + + public eeareturn(BigInteger s, BigInteger t) { + this.s = s; + this.t = t; + } + } + + /** + * executes the extended euclidean algorithm recursively + * @param a first number + * @param b second number + * @return eeareturn with s and t + */ + private static eeareturn eea(BigInteger a, BigInteger b) { + if (b.compareTo(a) > 0) { + eeareturn tmp = eea(b, a); + return new eeareturn(tmp.t, tmp.s); + } + + BigInteger q = a.divide(b); + BigInteger r = a.mod(b); + + if (r.compareTo(B0) == 0) { + // System.out.println(a + ", " + b + ", " + q + ", " + r + ", 0, 1"); + return new eeareturn(B0,B1); + } + + eeareturn alt = eea(b, r); + + // System.out.println(a + ", " + b + ", " + q + ", " + r + ", " + alt.t + ", " + (alt.s-q*alt.t)); + return new eeareturn(alt.t, alt.s.subtract(q.multiply(alt.t))); + } + + /** + * calculates the inverse d to e mod phi + * @return exponent for decryption for given encryption-exponent + * @throws Exception if phi not available + */ + private BigInteger findd() throws Exception { + if (this.phi == null) { + throw new Exception("you don't have the prime numbers!"); + } + return (RSA.eea(this.e,this.phi).s.add(this.phi)).mod(this.phi); + } + + /** + * calculates the inverse c to q mod p + * @return coefficient + * @throws Exception + */ + private BigInteger findcoefficient() throws Exception { + if (this.p == null) { + throw new Exception("you don't have the prime numbers!"); + } + return (RSA.eea(this.q,this.p).s.add(this.p)).mod(this.p); + } + + /** + * calculating the power to a given modulus + * @param b base + * @param e exponent + * @param mod modulus + * @return the result + */ + private static BigInteger modexp(BigInteger b, BigInteger e, BigInteger mod) { + BigInteger ret = B1; + + while (e.compareTo(B0)>0) { + if (e.mod(B2).compareTo(B1) == 0) { + ret = ret.multiply(b).mod(mod); + } + + b = b.multiply(b).mod(mod); + + e = e.divide(B2); + } + + return ret; + } + + /** + * encrypt a number + * @param m number within a String (automatically convert to BigInteger) + * @return the encypted number + * @throws Exception if no public key available + */ + public String encrypt(String m) throws Exception { + if (this.e == null || this.N == null) { + throw new Exception("you don't have a valid public key!"); + } + + return RSA.modexp(new BigInteger(m), this.e, this.N).toString(); + } + + /** + * decrypt a number + * @param m number within a String (automatically convert to BigInteger) + * @return the decrypted number + * @throws Exception if no private key available + */ + public String decrypt(String m) throws Exception { + if (this.d == null || this.N == null) { + throw new Exception("you don't have a valid private key!"); + } + + return RSA.modexp(new BigInteger(m), this.d, this.N).toString(); + } + + /** + * helper-function for printing public and private key + */ + public String toString() { + String ret = ""; + + if (this.e != null && this.N !=null) { + ret += "public key ("+this.e.toString()+","+this.N.toString()+")"; + } + if (this.d != null && this.N !=null) { + if (ret != "") ret += "\n"; + ret += "private key ("+this.d.toString()+","+this.N.toString()+")"; + } + if (ret == "") { + ret += "no key available!"; + } + + return ret; + } + + /** + * Miller-Rabin-Test for finding large prime numbers + * @param n number to test for prime + * @return true if probably prime + */ + private static boolean isProbablyPrime(BigInteger n) { + int j = 0; + BigInteger d = n.subtract(B1); + + if (n.compareTo(new BigInteger("5")) < 0) return false; + + while(d.mod(B2).compareTo(B0) == 0) { + j++; + d = d.divide(B2); + } + + int[] _a = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71}; + + for(int i=0; i<_a.length; i++) { + BigInteger a = new BigInteger(""+_a[i]); + if (a.compareTo(n.subtract(B2)) > 0) break; + + boolean isPrime = false; + + // System.out.println(a+"^"+d+"%"+n+"="+RSA.modexp(a, d, n)); + if (RSA.modexp(a, d, n).compareTo(B1) == 0) isPrime = true; + + if (isPrime) continue; + + for(int r = 0; r