# Verschlüsselung



## zerix (11. Juli 2005)

Hat hier sich schon mal jemand mit Verschlüsselung beschäftigt


----------



## Thomas Darimont (11. Juli 2005)

Hallo!


> Hat hier sich schon mal jemand mit Verschlüsselung beschäftigt


  Sicherlich hat sich "jemand" schon mal mit Verschlüsselung beschäftigt...
 Allein Google spuckt auf die Anfrage: http://www.google.de/search?hl=de&q=verschlüsselung+java&btnG=Google-Suche&meta=
  knapp 164.000 Hits aus *scnr*

  Gruß Tom


----------



## zerix (11. Juli 2005)

Ich hab nämlich dazu ne frage 

das sind ja alles rechnungen mit denen verschlüsselt wird. wie ich buchstaben in zahlen umwandle ist klar, aber wie kann ich das bei Dateien machen die keinen Text enthalten, z.b. ZIP-Dateien?
ich stehe da irgendwie auf dem schlauch und hab keine idee..

Kann mir da jemand helfen


----------



## HorstHorstmann (11. Juli 2005)

Auch Zip datein bestehen nur aus Symbolen und die kannste verschlüsseln.


----------



## zerix (11. Juli 2005)

Ich bräuchte ein beispiel wie ich eine Datei in zahlen umwandle, weil ich keine ahnung hab wie ich das bewerkstelligen soll


----------



## Thomas Darimont (11. Juli 2005)

Hallo!

 Schau mal hier:
http://java.sun.com/j2se/1.5.0/docs/guide/security/jce/JCERefGuide.html

 Gruß Tom


----------



## HorstHorstmann (11. Juli 2005)

int  c1 = 65;
char c2 = ’A’;

System.out.println( c1 );              // 65
System.out.println( (int)c2 );         // 65

Quelle dieses Beispiels:
http://www.galileocomputing.de/katalog/openbook/?GPP=opjiV

Also mit (int) 

Nunja musste die Datei nur noch Zeichenweise auslesen. Schau dazu in der API mal unter InputStreamReader nach. Leider kenn ich mich da auch noch nicht so genau aus, mein Problem steht drei Threads weiter unten  .
Lad dir mal die Javainsel runter da steht scho ne Menge drinne. (Link oben)


----------



## zerix (11. Juli 2005)

Danke schonmal, 

wie ich eine datei mit text umwandle ist mir schon klar, aber kann ich ne zip-datei genau so auslesen?

ich möchte ein programm mit RSA-Verschlüsselung schreiben und möchte diese Methode selbst entwickeln. Wenn man dateien verschlüsselt werden die ja größer, deshalb möchte ich die dateien vor der verschlüsselung komprimieren. nur ich weiß jetzt nicht wie ich die datei verschlüsseln kann, weil ich nicht weiß wie ich da irgendwas in zahlen umwandeln kann.


----------



## javaprogger1987 (11. Juli 2005)

Öhm.. prinzipiell bestehen Dateien ja nur aus Zahlen.. Die Zeichen erzeugt ja erst ein Editor..
Eine Datei besteht aus Bytes. Ein Byte hat 8 Bit (Bit: 0 oder 1), womit sich dann Zahlen bis 255 darstellen lassen. Jeder Zahl ist aber auch ein Zeichen zugeordnet (-> ASCII).
Ein Beispiel wie du Bytes auslesen kannst:


```
RandomAccessFile raf = new RandomAccessFile("C:\test.zip", "r"); //r=nur lesezugriff
//7 Bytes in das Array lesen
byte content[] = new byte[7];
raf.readFully(content);
```
Dann hast du im Array die Zahlen als Bytes stehen..
Zu beachten ist noch , das der Datentyp Byte von -128 bis 127 geht.
D.h. wenn ein Byte in der Datei den Wert 128 hat, würde in dem Array -128 stehen (256-128 = 128). anderes bsp. In der Datei steht ein Byte mit dem Wert 200. Im Array stünde dann -56 (256-56 = 200).

Hoffe das ist es was du meinst..


----------



## zerix (11. Juli 2005)

das mit byte hatte ich mir mal gedacht, aber wenn ich die zahl dann in der funktion benutze, kann ich es nachher nicht mehr als Byte schreiben, weil die zahl doch wesentlich größer ist als 255.


----------



## zerix (12. Juli 2005)

Ich hab das jetzt mal mit byte gemacht, jetzt hab ich nur das problem, wenn ich die verschlüsselung rückgängig mache, kommen bei den zahlen die größer waren als 255, also dann negative zahlen waren, nicht wieder das richtige raus.
wie kann man das denn lösen


----------



## javaprogger1987 (12. Juli 2005)

Zahlen die größer waren als 255 Das geht nicht wenn die Bytes verschlüsselt hast. Zahlen 
> 127 werden als negative dargestellt.

z.B.:

200 = -56 (als Byte, da > 127 deshalb wird es so berechnet: zahl(-56)+256 = 200).

D.h. wenn du eine Byte -56 hast, steht in der Datei eine 200(Als Byte, nicht als Text).

Oder was geht nicht?


----------



## zerix (12. Juli 2005)

Was passiert denn wenn die zahl über 200.000 ist? ich glaube dann kommt es nicht mehr so ganz hin, oder?


----------



## Thomas Darimont (12. Juli 2005)

Hallo!

   Hier mal ein Beispiel für asynchrone Verschlüsselung über Public Key Verfahren.
 Hierbei verwenden wir zum verschlüsseln den öffentlichen Schlüssel (Public Key) und zum entschlüsseln den privaten Schlüssel (private key).


```
package de.tutorials;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;

   public class SimpleChiffreExample {

   	/**
   	 * @param args
   	 */
   	public static void main(String[] args) throws Exception {

   		String data = "www.tutorials.de";

   		System.out.println("Plain text data: " + data);

   		Cipher cipher = Cipher.getInstance("RSA");
   		KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
   		cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());

   		ByteArrayOutputStream baosEncryptedData = new ByteArrayOutputStream();
   		CipherOutputStream cos = new CipherOutputStream(baosEncryptedData,
   				cipher);

   		cos.write(data.getBytes("UTF-8"));
   		cos.flush();
   		cos.close();

   		System.out.println("Encrypted data: "
 				+ new String(baosEncryptedData.toByteArray(),"UTF-8"));

   		cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
   		CipherInputStream cis = new CipherInputStream(new ByteArrayInputStream(
 				baosEncryptedData.toByteArray()), cipher);

   		ByteArrayOutputStream baosDecryptedData = new ByteArrayOutputStream();
   		byte[] buffer = new byte[8192];
   		int len = 0;
   		while((len = cis.read(buffer))> 0){
   			baosDecryptedData.write(buffer,0,len);
   		}
   		baosDecryptedData.flush();
   		cis.close();

   		System.out.println("Decrypted data: "
 				+ new String(baosDecryptedData.toByteArray(),"UTF-8"));

   	}
   }
```
 
   Gruß Tom


----------



## zerix (13. Juli 2005)

In welcher Java-Version ist das denn enthalten. Bei mir kommt nämlich der fehler dass für RSA kein algorithmus hätte


----------



## Thomas Darimont (13. Juli 2005)

Hallo!

 Habs mit der aktuellen Java 5 Version erstellt.

 Gruß Tom


----------



## zerix (13. Juli 2005)

Ok, dann muss ich mal warten bis ich an meinen rechner komme. Danke für deine Hilfe.

Ich möchte immer noch selbst ne RSA-Methode schreiben, das finde ich interessanter 

Mal schauen ob ich das hin bekomme


----------



## jean luc (18. Januar 2007)

Hallo !
das Beispiel funktioniert bei mir.
Allerdings gelingt es mir nicht die generierten Schlüssel zu speichern und so den Text auf einem anderen PC wieder zu entschlüsseln. In welchem Format sollte ich die Keys am besten abspeichern?

mfg
Simon


----------



## Thomas Darimont (18. Januar 2007)

Hallo!

Es kann sein, das auf den beiden Maschinen unterschiedliche encodings für Strings verwendet wurden. Wenn man unter Java einen String aus einem byte[] baut dann "sollte" man auch immer das gleiche Encoding verwenden. Dies kann man nur garantieren wenn man im Konstruktor von String das encoding mit angibt. -> Hab mein Beispiel (Auf Seite 1) entsprechend angepasst... versuchs noch mal.

Gruß Tom


----------



## big_boom_bang (28. Januar 2007)

Hallo,
ich hab eine kleine Frage an Thomas.
Und zwar erzeugt dein Programm ja den Key auf einem Rechner.
Wenn ich den jetzt aber zB. speichern oder übers Netz schicken möchte wie bekomme ich den dann und wie verschlüssele ich als "Fremder" mit dem publicKey

MfG Jens


----------



## Thomas Darimont (28. Januar 2007)

Hallo,

ganz einfach:
Du liest Deserialisierst den PublicKey den du geschickt bekommen hast und 
machst einfach das was in der encrypt Methode gezeigt wird:

```
PublicKey publicKey = readPublicKey(publicKeyFile);
        Cipher cipher = Cipher.getInstance(algorithm);
        String data = "www.tutorials.de";
        byte[] encryptedData = encrypt(data, cipher, publicKey);
        System.out.println("Encrypted data: "
                + new String(encryptedData, "UTF-8"));
```
Dann hast du das verschlüsselte byte[] an der Hand, welches du nun zum Server senden kannst.
Auf dem Server musst du's dann wie gehabt mit deinem privaten Schlüssel (den du dir irgendwo (sicher) abgespeichert hast (der Beispielsweise in deinem lokalen KeyStore liegt)) wieder entschlüsseln.

Hier ein kleines Beispiel:

```
/**
 * 
 */
package de.tutorials;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;

/**
 * @author Tom
 * 
 */
public class PublicKeyExample {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {

        String algorithm = "RSA";
        KeyPair keyPair = KeyPairGenerator.getInstance(algorithm)
                .generateKeyPair();
        File publicKeyFile = new File("c:/public.key");
        writeKey(keyPair.getPublic(), publicKeyFile);
        PublicKey publicKey = readPublicKey(publicKeyFile);

        Cipher cipher = Cipher.getInstance(algorithm);
        
        String data = "www.tutorials.de";
        byte[] encryptedData = encrypt(data, cipher, publicKey);
        System.out.println("Encrypted data: "
                + new String(encryptedData, "UTF-8"));

        String decryptedData = decrypt(encryptedData, cipher, keyPair
                .getPrivate());
        System.out.println("Decrypted data: " + decryptedData);

    }

    private static String decrypt(byte[] encryptedData, Cipher cipher,
            PrivateKey privateKey) throws Exception {
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        CipherInputStream cis = new CipherInputStream(new ByteArrayInputStream(
                encryptedData), cipher);
        ByteArrayOutputStream baosDecryptedData = new ByteArrayOutputStream();
        byte[] buffer = new byte[8192];
        int len = 0;
        while ((len = cis.read(buffer)) > 0) {
            baosDecryptedData.write(buffer, 0, len);
        }
        baosDecryptedData.flush();
        cis.close();
        return new String(baosDecryptedData.toByteArray(), "UTF-8");
    }

    private static byte[] encrypt(String data, Cipher cipher,
            PublicKey publicKey) throws Exception {

        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        ByteArrayOutputStream baosEncryptedData = new ByteArrayOutputStream();
        CipherOutputStream cos = new CipherOutputStream(baosEncryptedData,
                cipher);
        cos.write(data.getBytes("UTF-8"));
        cos.flush();
        cos.close();
        return baosEncryptedData.toByteArray();
    }

    private static PublicKey readPublicKey(File file) throws Exception {
        ObjectInputStream objectInputStream = new ObjectInputStream(
                new FileInputStream(file));
        PublicKey publicKey = (PublicKey) objectInputStream.readObject();
        objectInputStream.close();
        return publicKey;
    }

    private static void writeKey(PublicKey publicKey, File file)
            throws Exception {
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(
                new FileOutputStream(file));
        objectOutputStream.writeObject(publicKey);
        objectOutputStream.close();
    }
}
```

Gruß Tom


----------



## big_boom_bang (29. Januar 2007)

Hi,
super dankeschön.
Jetzt hab ich nur noch eine Frage zur Sicherheit.
Wie lange kann ich ein Paar verwenden
Also bei jeder Nachricht eine neues(kann ich mir ja nicht vorstellen) oder für ein Jahr ein paar.
MfG bigboombang


----------



## jean luc (29. Juni 2007)

Hallo,
ich habe dieses Beispiel auch verwendet. Allerdings habe ich jetzt ein Problem mit Windows Vista. Wenn ich ein Keypair erstelle und einen Text verschlüssele funktioniert die Entschlüsselung auf Windows XP normal. Auf Windows Vista allerdings nicht. Leider habe ich dazu keine Fehlermeldung da ich selber kein Vista habe. Aber ich habe diese Info von verschiedenen Vista Nutzern bekommen. 
Kann sich jemand vorstellen, wo da das Problem liegt?

Grüße 
Jean Luc


----------



## benni84 (10. April 2008)

Hallo Thomas,

dein Beispiel finde ich sehr gut. Auf basis deines Beispieles habe ich mir ein kleines Tool gebastelt um Strings zu verschlüsseln. Ich habe dabei folgendes Problem. Es gibt bestimmte Strings wie z.B "CGO" die lassen sich zwar verschlüsseln, jedoch beim Entschlüsseln erscheint nur ein leerstring.

Ich habe auch schon andere Verschlüsselungsmethoden oder CharacterSets probiert. Das Problem ist das gleiche, nur dass die Strings die nicht verarbeitet werden können andere sind.

Jetzt stehe ich völlig auf dem Schlauch

Ich hoffe du kannst mir helfen.



```
public class PasswortCrypter {

	Cipher cipher;
	Key key;

	/**
	 * Standardkonstruktor
	 */
	public PasswortCrypter(){
		// Chipher und Key erzeugen
		try {
			setCipher(Cipher.getInstance("AES"));
			setKey(new SecretKeySpec( "3g06kg64öj923h46".getBytes(), "AES" ));

		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	public String encrypt(String data) {

		try {
			
			// Chipher auf Verschlüsselungsmodus setzen und Schlüssel festlegen
			getCipher().init(Cipher.ENCRYPT_MODE, getKey());

			
			ByteArrayOutputStream baosEncryptedData = new ByteArrayOutputStream();
			CipherOutputStream cos = new CipherOutputStream(baosEncryptedData,cipher);
			
			// Verschlüsseltes ByteArray schreiben
			cos.write(data.getBytes());
			cos.flush();
			cos.close();

			// String aus dem verschlüsselten Byte Array zurückliefern
			return new String(baosEncryptedData.toByteArray());

		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} 

	}


	public String decrypt(String data) {

		try {
			
			// Chipher auf Entschlüsselungsmodus setzen und Schlüssel festlegen
			getCipher().init(Cipher.DECRYPT_MODE, getKey());

			CipherInputStream cis = new CipherInputStream(new ByteArrayInputStream(data.getBytes()), cipher);

			ByteArrayOutputStream baosDecryptedData = new ByteArrayOutputStream();

			

			int len = 0;

			while((len = cis.read())> 0){
				// Entschlüsseltes Byte Array schreiben
				baosDecryptedData.write(len);

			}

			baosDecryptedData.flush();

			cis.close();

			// String aus dem Entschlüsselten Byte Array zurückliefern
			return new String(baosDecryptedData.toByteArray());


		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} 
	}



	// Getter und Setter Methoden
	private Cipher getCipher() {
		return cipher;
	}


	private void setCipher(Cipher cipher) {
		this.cipher = cipher;
	}


	private Key getKey() {
		return key;
	}


	private void setKey(Key key) {
		this.key = key;
	}


	/**
	 * Dies ist ein Programm womit der Anwender aus einem String ein Verschlüsseltes Passwort
	 * erstellen kann. (anhand von JOptionPane Input Dialogen)
	 * 
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {

		if(JOptionPane.showOptionDialog(null, "Möchten Sie ver- oder entschlüsseln?", "Crypt", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new String[]{"Verschlüsseln","Entschlüsseln"}, null) == 0){
			// Benuter ein Passwort eingeben lassen
			String pw = JOptionPane.showInputDialog("Bitte geben Sie das zu verschlüsselnde Passwort ein");
			
			// Verschlüsseltes Passwort ausgeben
			JOptionPane.showInputDialog(null, "Dies ist das verschlüsselte Passwort", "", JOptionPane.INFORMATION_MESSAGE, null, null, new PasswortCrypter().encrypt(pw));
		}else{
			// Benuter ein Passwort eingeben lassen
			String pw = JOptionPane.showInputDialog("Bitte geben Sie das verschlüsselte Passwort ein");
			
			// Verschlüsseltes Passwort ausgeben
			JOptionPane.showInputDialog(null, "Dies ist das entschlüsselte Passwort", "", JOptionPane.INFORMATION_MESSAGE, null, null, new PasswortCrypter().decrypt(pw));
		}
	}
}
```


----------



## reaper81 (4. November 2008)

Servus,

ich muss mittelgroße xml-dateien verschlüsselt auf der Platte ablegen und zur Anzeige im Programm auch wieder entschlüsseln. Hab das beispiel von thomas darimont ausprobiert ausprobiert, scheint idiotensicher, läuft ohne Exceptions durch.

Mein Problem: Es kommt nichts raus, der ByteArrayOutputStream ist leer,  
                       nichts drin, wird nicht gefüllt. 

Mein Code zum Vergleich:

public byte[] encrypt(String Data){
try {
byte unverschlByte[]=Data.getBytes("UTF-8");	
	    	      Cipher cipher = Cipher.getInstance("RSA");
	    	      cipher.init(Cipher.ENCRYPT_MODE, publicKey);
	    	      ByteArrayOutputStream baos = new ByteArrayOutputStream();
	    	      CipherOutputStream cos = new 
                      CipherOutputStream(baos,cipher);
	    	      cos.write(unverschlByte);
	    	      cos.flush();
	    	      cos.close();
	    	      return baos.toByteArray();​		} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
			return null;​		}​	}

Kann es sein dass man nur sehr kurze Strings damit verschlüsseln kann?


----------

