master
akimmig 2021-04-28 13:06:57 +02:00
commit 41eeed22bb
6 changed files with 519 additions and 0 deletions

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-13">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

1
Verschlüsselung/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/bin/

17
Verschlüsselung/.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Verschlüsselung</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -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

View File

@ -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());
}
}

View File

@ -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<j; r++) {
BigInteger exp = d.multiply(B2.pow(r));
// System.out.println(a+"^"+exp+"%"+n+"="+RSA.modexp(a, exp, n));
if (RSA.modexp(a, exp, n).compareTo(n.subtract(B1)) == 0) {
isPrime = true;
}
if (isPrime) break;
}
if (!isPrime) return false;
}
return true;
}
/**
* find a prime number
* @param bits length of the prime number
* @return prime number
*/
public static String generatePrime(int bits) {
Random rand = new Random();
BigInteger prime = new BigInteger(bits, rand);
// System.out.println(isProbablyPrime(new BigInteger("17")));
// System.out.println("trying " + prime);
while(!isProbablyPrime(prime)) {
prime = new BigInteger(bits, rand);
// System.out.println("trying " + prime);
}
return prime.toString();
}
/**
* generates the content for the public key file
* @return String
*/
public String toPublicFileString() {
String ret = "";
// add sequence
{
String seqdata = "";
// add RSA identifier
seqdata += asn1field("06", "2A864886F70D010101");
// add NULL
seqdata += "0500";
ret += asn1field("30", seqdata);
}
// add bit string
{
String bsdata = "";
// add sequence with modulus and exponent
{
String seqdata = "";
// add modulus
seqdata += asn1field("02", "00" + this.N.toString(16));
// add exponent
seqdata += asn1field("02", this.e.toString(16));
bsdata += asn1field("30", seqdata);
}
ret += asn1field("03", "00" + bsdata);
}
return "-----BEGIN PUBLIC KEY-----\n" + Base64.getEncoder().encodeToString(hex2byte(asn1field("30", ret))).replaceAll("(.{64})", "$1\n") + "\n-----END PUBLIC KEY-----";
}
/**
* generates the content for the private key file
* @return String
*/
public String toPrivateFileString() throws Exception {
String ret = "";
// add 0
ret += asn1field("02", "00");
// add N
ret += asn1field("02", "00" + this.N.toString(16));
// add e
ret += asn1field("02", this.e.toString(16));
// add d
ret += asn1field("02", "00" + this.d.toString(16));
// add p
ret += asn1field("02", "00" + this.p.toString(16));
// add q
ret += asn1field("02", "00" + this.q.toString(16));
// add d%(p-1)
ret += asn1field("02", "00" + this.d.mod(this.p.subtract(new BigInteger("1"))).toString(16));
// add d%(q-1)
ret += asn1field("02", "00" + this.d.mod(this.q.subtract(new BigInteger("1"))).toString(16));
// add coefficient
ret += asn1field("02", this.findcoefficient().toString(16));
return "-----BEGIN RSA PRIVATE KEY-----\n" + Base64.getEncoder().encodeToString(hex2byte(asn1field("30", ret))).replaceAll("(.{64})", "$1\n") + "\n-----END RSA PRIVATE KEY-----";
}
/**
* generating a ASN 1 entry
* @param type Type of the ASN 1 field
* @param content Content of the ASN 1 field
* @return the encoded string (hex-number as string)
*/
private static String asn1field(String type, String content) {
String ret = type;
content = fill(content);
int length = content.length();
if (length < 128) {
ret += fill(Integer.toHexString(length/2)).toUpperCase();
} else {
String bytelength = fill(Integer.toHexString(length/2));
int bytes = bytelength.length()/2;
ret += "8" + bytes + bytelength;
}
ret += content.toUpperCase();
return ret;
}
/**
* helper-function for filling up a hex-string with a leading zero
* @param s hex-string
* @return
*/
private static String fill(String s) {
if (s.length() % 2 == 0) return s;
return "0" + s;
}
/**
* convert a hex-string to a byte-array
* @param hex
* @return byte[]
*/
private static byte[] hex2byte(String hex) {
byte[] b = new byte[hex.length()/2];
for (int i=0; i<hex.length(); i+=2) {
b[i/2] = (byte) Integer.parseInt("" + hex.charAt(i)+hex.charAt(i+1), 16);
}
return b;
}
}