String in KeyObjekt konvertieren

pas

Grünschnabel
Hallo zusammen

Erst einmal danke an alle hier in diesem Forum. Ihr habt mir schon sehr viel geholfen:)

Ich bin blutiger Anfänger in Java. Und komme bei folgendem Problem, trotz langem googeln einfach nicht weiter.

Ich möchte aus einem rsa-public-key, welcher als Textfile vorliegt, wieder ein Keyobjekt erstellen.

Der Inhalt des Files sieht so aus (modulus habe ich gekürzt):

Sun RSA public key, 2048 bits
modulus: 17297892459927537333 ...
public exponent: 65537


Erstellt habe ich die Schüssel mit:

Code:
public void KeyGen(String Methode) {
		KeyPair keyPair = null;
		try {
	        KeyPairGenerator pairgen = KeyPairGenerator.getInstance(Methode);
	        SecureRandom random = new SecureRandom();
	        pairgen.initialize(2048, random);
	        keyPair = pairgen.generateKeyPair();
	        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("publicKey."+Methode));
	        out.writeObject(keyPair.getPublic());
	        out.close();
	        out = new ObjectOutputStream(new FileOutputStream("privateKey."+Methode));
	        out.writeObject(keyPair.getPrivate());
	        out.close();
	    } catch (IOException e) {
	        System.out.println("Exception Message:\n\n" + e.getMessage());
	    } catch (GeneralSecurityException e) {
	    	System.out.println("Exception Message:\n\n" + e.getMessage());
	    }
	    //System.out.println("PublicKey: " + keyPair.getPublic());
	    //System.out.println("PrivateKey: " + keyPair.getPrivate());
	    textPrivateKey.setText(keyPair.getPrivate().toString());
	    textPublicKey.setText(keyPair.getPublic().toString());
	}


Mit den binär gespeicherten Schlüsseln kann ich zwar Ver- und Entschlüsseln, ich brauche aber noch die Möglichkeit einen PublicKey aus einem String zu lesen und in java zu verwenden.

Ist sicher eine peinliche Anfängerfrage, aber ich komme hier einfach nicht weiter:(

Hoffe ich habe mich einigermassen verständlich aussgedrückt.
Dank schon mal.
 
Hallo,

schau mal hier:
Java:
package de.tutorials;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;

public class PublicPrivateKey {

	public static void main(String[] args) throws Exception {
		String algo = "RSA";
		KeyPairGenerator pairgen = KeyPairGenerator.getInstance(algo);
		SecureRandom random = new SecureRandom(new byte[] { 1, 2, 3, 4, 5 });
		pairgen.initialize(2048, random);
		KeyPair keyPair = pairgen.generateKeyPair();
		
		String pubKeyPath = "publicKey." + algo;
		String privKeyPath = "privateKey." + algo;
		
		writeObj(keyPair.getPublic(), pubKeyPath);
		writeObj(keyPair.getPrivate(), privKeyPath);
		
		System.out.println("PublicKey: " + keyPair.getPublic());
		System.out.println("PrivateKey: " + keyPair.getPrivate());
		
		Key privKey = readObj(privKeyPath);
		Key pubKey = readObj(pubKeyPath);
		
		System.out.println(keyPair.getPrivate().equals(privKey));
		System.out.println(keyPair.getPublic().equals(pubKey));
		
	}

	private static Key readObj(String path) throws Exception{
		ObjectInputStream in = new ObjectInputStream(new FileInputStream(path));
		Key key = (Key)in.readObject();
		in.close();
		return key;
	}

	private static void writeObj(Key key, String path) throws Exception{
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path));
		out.writeObject(key);
		out.close();
		
	}
}

Gruß Tom
 
  • Gefällt mir
Reaktionen: pas
Hallo Tom

Danke Dir, und sorry dass ich die Frage im falschen Forum gestellt habe.
Aber ist es auch möglich ein Key-Object, Sinngemäss in der folgenden Art anzulegen :

String modulus = "1729789245992753733301...";
String exponent = "65537";
Key privateKey = (Key) modulus + exponent;

Gruss pas
 
http://download.oracle.com/javase/7/docs/api/java/math/BigInteger.html
http://download.oracle.com/javase/7/docs/api/java/security/Key.html
http://download.oracle.com/javase/7/docs/api/java/security/PrivateKey.html
http://download.oracle.com/javase/7/docs/api/java/security/PublicKey.html
http://download.oracle.com/javase/7/docs/api/java/security/interfaces/RSAPrivateKey.html
http://download.oracle.com/javase/7/docs/api/java/security/interfaces/RSAPublicKey.html
http://download.oracle.com/javase/7/docs/api/java/security/spec/RSAPrivateKeySpec.html
http://download.oracle.com/javase/7/docs/api/java/security/spec/RSAPublicKeySpec.html
http://download.oracle.com/javase/7/docs/api/java/security/KeyFactory.html

das sind alle klassen die du für import und export von RSA-Keys brauchst wenn du KEINE Object-Streams verwenden willst

hier mal beispiel methoden
ACHTUNG : diese methoden sind nicht getestet nur on-the-brain geschrieben ...
ich bitte daher die profis hier *unter anderem Thomas und Kai008* um überprüfung und ggf korrektur da ich zur zeit kein JDK zur verfügung habe

EXPORT
Java:
public void exportRSAPublic(RSAPublicKey key)
{
	//PublicExponent und Modulus als HEX-Strings speichern
	String exp=key.getPublicExponent().toString(16);
	String mod=key.getModulus().toString(16);
	//File-Object und PrintStream zum speichern
	File file=new File("public.key");
	PrintStream printStream=new PrintStream(new FileOutputStream(file));
	//PublicExponent und Modulus schreiben
	printStream.print(exp+"\n"+mod);
	//Stream closen
	printStream.close();
}
public void exportRSAPrivate(RSAPrivateKey key)
{
	//PriavteExponent und Modulus als HEX-Strings speichern
	String exp=key.getPrivateExponent().toString(16);
	String mod=key.getModulus().toString(16);
	//File-Object und PrintStream zum speichern
	File file=new File("private.key");
	PrintStream printStream=new PrintStream(new FileOutputStream(file));
	//PrivateExponent und Modulus schreiben
	printStream.print(exp+"\n"+mod);
	//Stream closen
	printStream.close();
}

IMPORT
Java:
public RSAPublicKey importRSAPublic()
{
	//File-Object und BufferedReader zum einlesen
	File file=new File("public.key");
	BufferedReader bufR=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
	//PublicExponent und Modulus einlesen
	String exp=bufR.readLine();
	String mod=bufR.readLine();
	//BufferedReader closen
	bufR.close();
	//RSAPublicKeySpec erzeugen -> wichtig für die KeyFactory
	RSAPublicKeySpec pubKeySpec=new RSAPublicKeySpec(new BigInteger(mod, 16), new BigInteger(exp, 16));
	//RSA KeyFactory erzeugen
	KeyFactory keyFactory=KeyFactory.getInstance("RSA");
	//RSAPublicKey erzeugen
	RSAPublicKey pubKey=(RSAPublicKey)keyFactory.generatePublic(pubKeySpec);
	//returnen
	return pubKey;
}
public RSAPrivateKey importRSAPrivate()
{
	//File-Object und BufferedReader zum einlesen
	File file=new File("private.key");
	BufferedReader bufR=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
	//PrivateExponent und Modulus einlesen
	String exp=bufR.readLine();
	String mod=bufR.readLine();
	//BufferedReader closen
	bufR.close();
	//RSAPrivateKeySpec erzeugen -> wichtig für die KeyFactory
	RSAPrivateKeySpec privKeySpec=new RSAPrivateKeySpec(new BigInteger(mod, 16), new BigInteger(exp, 16));
	//RSA KeyFactory erzeugen
	KeyFactory keyFactory=KeyFactory.getInstance("RSA");
	//RSAPrivateKey erzeugen
	RSAPrivateKey privKey=(RSAPrivateKey)keyFactory.generatePrivate(pubKeySpec);
	//returnen
	return privKey;
}

das ganze entweder mit throws Exception deklarieren oder die try/catch-blöcke setzen

wie gesagt : das ist jetzt nur ausm kopf geschrieben ... und eine eher umständliche methode ... vllt fällt den profis hier noch ne bessere lösung ein ... aber für den anfang würde es erstmal reichen
ich persönlich bin aber immer noch der überzeugung das dierektes speichern und lesen über ObjectStreams ein paar zeilen sparen würde und einfacher wäre
achtung : im verwendeten beispiel werden die "zahlen" als HEX-strings verarbeitet ... wenn du aber DEC-zahlen verwendest/verwenden willst/musst dann einfach die 16 bei den toString methoden und den BigInteger konstruktoren weglassen

noch ne bemerkung was das checken mit equals angeht : wenn du ein RSA keypair erzeugst wird in der regel ein RSAPrivateCrtKey erzeugt ... wenn du aber mit meinen methoden exportierst und dann wieder importierst hast du nur einen RSAPrivateKey ... darum wird in einer test-klasse ein if(equals) der beiden private-keys false ergeben
 
Zuletzt bearbeitet von einem Moderator:
das freut mich das meine ausm kopf zusammengebastelte variante funktioniert ... wie gesagt ... wenn du es mit normalen dezimalen zahlen machen willst einfach die 16 weglassen oder durch 10 ersetzen ...
wenn du hex-zahlen nimmst sparst du eventuell hier oder da das eine oder andere byte ... aber es macht keinen merklichen unterschied
wenn du unter windows die key-files im editor ansiehst wundere dich nicht das beide zahlen in der selben zeile stehen ... für windows ist der line.seperator \r\n ... ich habe hier aber das einfache \n genutz was von java und den meisten anderen sprachen bereits als line.seperator akzeptiert wird ...
und unter linux / mac ist es sowieso der standard ...

was den unterschied RSAPrivateKey und RSAPrivateCrtKey angeht ...
das CRT steht für Chinese Remainder Theorem ... auf deutsch : Chinesischer Restatz
es beschreibt *soweit ich in bezug auf RSA weiß* eine möglichkeit den rechenaufwand zu verringern in dem man nicht den PrivateExponent sondern die primzahlen P und Q so wie deren Exponenten und einem CRT-Koeffizienten verwendet ...
ich hab aus langerweile mal mit nem 2048-Bit RSA und nanoseconds geprüft ... auf nem DualCore mit 2x 3.00Ghz und 2GB RAM kommt man auf wenige millisekunden ... also kaum merkbar ...
ich kann mir aber vorstellen das grade in bezug auf SSL und HTTP ein gewisser nutzen merklich wird wenn hunderte parallel ablaufenden RSA-DeCrypts erfolgen ... aber in heutiger zeit müsste man schon wahnwitzige 4096Bit oder 8192Bit lange RSA keys nehmen um da merkliche resultate zu erzielen ...
zieh dir einfach mal die API rein ... einfach die zusätzlichen zahlen noch mit in die export und import methoden reinpacken und dann bekommt man auch wieder einen RSAPrivateCrtKey ... aber der zeitverlust beim einlesen der größeren datenmenge ist größer als der zeitgewinn beim schnelleren decrypten ...

ich habe hier auch irgendwo mal n link zu einem von mir geschriebenen hybrid-kryptosystem rumfliegen das RSA und AES verwendet ... der AES-key wird über RSA ausgetauscht und die eigentliche kommunikation dann über AES abgewikelt wie es in der praxis z.b. bei SSL anwendung findet
 
Zuletzt bearbeitet von einem Moderator:
Danke SPiKEe für Zusatzinfos, sehr spannendes Thema.
Und sorry dass ich mich erst jetzt wieder melde.
Aber ich schreibe gerade zum ersten mal ein Programm in Java.
Ich habe eine menge zu lehrnen, Eclips, swt, gwt, IZpack, SQL (auffrischen) und und und - macht aber echt spass:)

Dank noch mal
 
Zurück