# Sicherheitscode generieren



## mtk-flo (14. Juni 2007)

Hallo,

Ich möchte ein eigenes Sicherheitssystem programmieren.

Ich möchte anhand eines Schlüssels einen Code generieren.
Der Code sollte sich möglichs nie wiederholen...

Jedoch will ich über den Schlüssel den Code prüfen können.

Ist sowas möglich !?
Wie ist da die Programmier-Logik ?!


----------



## limago (14. Juni 2007)

Hi, 

ist in Java alles eingebaut. Keystores, Keygeneratoren, Sicherheitszertifikate können erzeugt und geprüft werden. Datenströme kannst Du verschlüsseln. Dazu kannst Du mit dem Progamm Keygen, das mit Java mitgeliefert wird, die Schlüsselpaare erzeugen.

Oder so:

```
try {
        // Generate a 1024-bit Digital Signature Algorithm (DSA) key pair
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
        keyGen.initialize(1024);
        KeyPair keypair = keyGen.genKeyPair();
        PrivateKey privateKey = keypair.getPrivate();
        PublicKey publicKey = keypair.getPublic();
    
        // Generate a 576-bit DH key pair
        keyGen = KeyPairGenerator.getInstance("DH");
        keyGen.initialize(576);
        keypair = keyGen.genKeyPair();
        privateKey = keypair.getPrivate();
        publicKey = keypair.getPublic();
    
        // Generate a 1024-bit RSA key pair
        keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(1024);
        keypair = keyGen.genKeyPair();
        privateKey = keypair.getPrivate();
        publicKey = keypair.getPublic();
    } catch (java.security.NoSuchAlgorithmException e) {
    }
```

Du schreibst:


mtk-flo hat gesagt.:


> Jedoch will ich über den Schlüssel den Code prüfen können.



Wenn Du damit meinst, dass Du JARfiles signieren willst, dann geht das mit Keygen. Damit kannst Du ein Zertifikat erstellen, und den Javacode damit schützen. Das Verfahren kann ich aber nicht in 5 Minuten erklären. 

Ich verstehe nicht was Du genau brauchst, aber schau mal hier.

http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html und hier http://www.exampledepot.com/egs/java.security/pkg.html?l=rel#Key Store

oder einfach mal nach Security oder Crypto und Java googlen.

Muss leider Arbeiten gehen, sonst würde ich ein Beispiel einstellen.


----------



## Kulabac (14. Juni 2007)

Also möglich ist das was du suchst auf jeden Fall. Aber wie es genau funktioniert, kann ich dir auch nicht erklären.

Wenn man im Internet Verzeichnisse schützen will, funktioniert das, indem man in das entsprechende Verzeichnis eine .htaccess-Datei und eine .passwd-Datei hinterlegt. In dieser Datei sind Benutzernamen und Passwörter abgelegt. Die Passwörter sind verschlüsselt - das tolle ist, dass identische Passwörter niemals gleich aussehen. Trotzdem kann natürlich kontrolliert werden ob das eingegebene Passwort richtig ist. Ich vermute das funktioniert dann über den Hash-Wert davon. 

Wie gesagt, wie es funktioniert weiß ich auch nicht. Wollte dir damit jetzt nur einen Hinweis darauf geben, nach welchem Algorithmus du mal im Netz suchen kannst. Vielleicht ist er ja auch schon bei dem bei, was limago empfohlen hat


----------



## mtk-flo (14. Juni 2007)

Im Prinzip möchte ich aus einem speziellen Wort (z.B.: "Fotoaperat") ein hash bilden, der sich aber kaum wiederholt....

geb ich den Hash-Wert in mein Programm ein, soll das Wort "Fotoaperat" erscheinen...
Somit will ich dir Gültigkeit prüfen....


----------



## zerix (14. Juni 2007)

Hallo,

da Hashfunktionen Einwegfunktionen sind, ist es unmöglich aus einem Hashwert ursprüngliche Wort oder was es auch immer war wiederherzustellen.

Schau mal hier 
http://de.wikipedia.org/wiki/Hash-Funktion

MFG

zEriX


----------



## mtk-flo (14. Juni 2007)

Dann eben ohne ein Hash...
Aber von der Vorgehensweise gleich....


----------



## zerix (14. Juni 2007)

Ich weiß ja nicht wie die Werte generiert werden sollen oder wie das alles funktionieren soll, aber bei dem was ich im moment weiß, würde ich sagen, dass es es doch einfach mit Verschlüsselung machen kannst.

Wenn du den String verschlüsselst, ist er nachher nicht mehr lesbar und wenn du ihn entschlüsselst, ist er wieder lesbar. 

Aber ich verstehe nicht so ganz was du machen willst. Warum sollte jetzt um bei dem Hash-Beispiel zu bleiben jemand ein Hashwert eingeben? 
Eigentlich gibt man doch das richtige Wort ein, errechnet daraus den Hashwert und vergleicht diesen mit dem abgespeicherten Hashwert.

MFG

zEriX


----------



## limago (14. Juni 2007)

Habe gerade keine Zeit, nur so viel dazu: Man kann aus dem Hashcode des Objects und dem privaten schlüssel eine Signatur erzeugen. Diese Signatur kann mit dem öffentlichen Schlüssel verifiziert werden. 

Dazu braucht man "Zertifikate". Diese werden mit "keygen" erzeugt und in einem "keystore" abgelegt.

google doch mal zu diesen Begriffen.... Code folgt, wenn ich Zeit habe.

Gruss


----------



## limago (14. Juni 2007)

Mit Hilfe der Klasse MessageDigest kannst Du einen Hash zu dem String erzeugen:


```
package de.tutorials;

import java.security.MessageDigest;

public class DigestDemo {

	
	public static void main(String[] args) throws Exception {
			MessageDigest messageDigest =
			MessageDigest.getInstance("SHA-256");
			String stext ="Dieser Text soll einen Hash bekommen" ;
			messageDigest.update( stext.getBytes("UTF8") );
			byte [] hashwert = messageDigest.digest();
			
	}

}
```

So erzeugst Du eine Signatur aus einem String mit dem privaten Schlüssel und verifizierst mit öffentlichem Schlüssel. Dies ist ein simples Beispiel. Besser ist es mit Keystore und Zertifikaten zu arbeiten....


```
package de.tutorials;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

public class Schluessel {

	private PublicKey publicKey;

	private PrivateKey privateKey;

	public Schluessel() throws Exception {

		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(512);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		publicKey = keyPair.getPublic();
		privateKey = keyPair.getPrivate();
	}

	public byte[] createSignature(String meinText) throws Exception {
		Signature signature = Signature.getInstance("MD5WithRSA");
		signature.initSign(privateKey);
		signature.update(meinText.getBytes("UTF8"));
		return signature.sign();
	}

	public boolean verify(String meinText, byte[] signatur) throws Exception {
		Signature sig = Signature.getInstance("MD5WithRSA");
		sig.initVerify(publicKey);
		sig.update(meinText.getBytes("UTF8"));
		return sig.verify(signatur);
	}

	private void run() {
		try {
			String textZumSignieren = "Dieser Text darf nicht verändert werden";
			// Signatur erstellen;
			byte[] mySignature = createSignature(textZumSignieren);
			
			if (verify(textZumSignieren, mySignature))
				System.out.println("Text ist unverändert!");
			else
				System.out.println("ACHTUNG: Text wurde verändert!");

			
			textZumSignieren = "neuer Text!";
			if (verify(textZumSignieren, mySignature))
				System.out.println("Text ist unverändert!");
			else
				System.out.println("ACHTUNG: Text wurde verändert!");

		} catch (Exception e) {

			e.printStackTrace();
		}
	}

	public static void main(String[] args) throws Exception {

		new Schluessel().run();
	}

}
```


----------



## limago (14. Juni 2007)

Während man mit dem privaten schlüssel die Signatur erstellt und sie mit dem öffentlichen schlüssel prüft, Kann man mit dem öffentlichen Schlüssel verschlüsseln und mit dem privaten entschlüsseln....


```
package de.tutorials;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;

import javax.crypto.Cipher;

public class Schluessel {

	private PublicKey publicKey;

	private PrivateKey privateKey;

	public Schluessel() throws Exception {

		//Security.addProvider(new java.security.AuthProvider());

		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(512);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		publicKey = keyPair.getPublic();
		privateKey = keyPair.getPrivate();
	}

	public byte[] encrypt(String text) throws Exception {

		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] cipherText = cipher.doFinal(text.getBytes());
		return cipherText;
	}

	public String decrypt(byte [] geheimerText) throws Exception{
		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		return new String( cipher.doFinal(geheimerText));
		
	}

	private void run() {
		try {
			String textZumVerschluesseln = "Dieser Text ist geheim!";
			byte [] geheim = encrypt(textZumVerschluesseln);
			System.out.println(new String(geheim));
			
			String klarText = decrypt(geheim);
			
			System.out.println(klarText);
			
			

		} catch (Exception e) {

			e.printStackTrace();
		}
		/*
		Provider [] providers = Security.getProviders();
		for (int i = 0; i < providers.length; i++) {
			System.out.println(providers[i].getName());
		}
		*/
	}

	public static void main(String[] args) throws Exception {

		new Schluessel().run();
	}

}
```

gruss


----------



## limago (15. Juni 2007)

Hi,

Klarstellung: *Meine Code Beispiele sind nicht immer sicher*, sondern vielmehr als Skizze zu verstehen. Sie sollen nur grundsätzliche die technische Implementierung zeigen.

Die Methode "verify" zum Beispiel testet nur, ob die Signatur zum Public Key passt. Mehr nicht. Um die Sicherheitsproblematik zu zeigen, nehmen wir folgende Situation an. Ein Sender schickt 2 Mails an den Empfänger. Eine enthält den Public Key und eine den Text mit der Signatur. Ein Angreifer fängt beide ab und tauscht sowohl Schlüssel als auch die Signatur durch eigene. Eine Änderung in der Nachricht ist durch den Empfänger nicht mehr feststellbar.

Deswegen braucht man Zertifikate. Diese können bei einer Zertifizierungsstelle (z.B. VersiSign) beantragt werden. Dazu schickt man Angaben zur Person (Firma oder Server) an diese Stelle.  Von der Zertifizierungsstelle werden diese Daten auf Echtheit geprüft. (z.B. Postident, Vorlage Personalausweis , oä). Wenn die Angaben stimmen, wird ein Zertifikat mit diesen Angaben und einem Schlüsselpaar erzeugt und diese Daten werden von VeriSign (oder wem auch immer) digital signiert.

Dieses Zertifikat speichert der Sender in einem Keystore. Signaturen erstellt er jetzt mit dem privaten Schlüssel aus seinem Zertifikat. Statt dem Public Key kann er nun in seiner Mail den öffentlichen Teil des Zertifikats senden. Ein Empfänger kann jetzt die Echtheit der Absenderangaben und damit die Authentzität des Public Key mit dem öffentlichen Key von VeriSign überprüfen. Eine "Man in Middle"-Attacke fällt auf. 

Den öffentlichen Teil des Zertifikats kann der Empfänger seinerseits in einem Truststore speichern und bei Bedarf Daten mit dem Public Key aus dem Zertifikat verschlüsseln und zurücksenden.

In eine Richtung kann man also mit dem Zertifikat digital signieren und in die andere Richtung verschlüsseln.

Hoffe ich habe das einigermassen klar ausgedrückt.

Gruss

EDIT:

Bei vielen Anbietern sind Zertifikate für Privatpersonen kostenlos. Mit keygen kann man übrigends auch "Eigenzertifikate" erstellen. Damit kann man im Intranet oder zu Testzwecken arbeiten.


----------

