Bild verschlüsseln

sebastianb

Erfahrenes Mitglied
Hallo zusammen,

aus Spaß an der Sache wollte ich gerade ein Beispiel von Thomas, das ich hier im Forum gefunden habe, ein wenig erweitern. Ziel sollte es eigentlich sein ein Bild einzulesen um es danach wieder verschlüsselt abzuspeichern, nur leider will mein vll etwas naiver Lösungsansatz nicht so richtig.

Java:
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
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;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

public class Temp
{

   private static byte[] loadImage() throws IOException
   {
      File file = new File("c:/krypto/test.jpeg");
      
      BufferedImage bufferedImage = ImageIO.read(file);

      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
      
      ImageIO.write(bufferedImage, "jpeg", byteArrayOutputStream);
      
      return byteArrayOutputStream.toByteArray();
   }
   
   private static void saveImage(byte[] image) throws IOException
   {
      File file = new File("c:/krypto/test.cry");
      
      FileOutputStream foStream = new FileOutputStream(file);

      ByteArrayOutputStream oStream = new ByteArrayOutputStream();

      oStream.write(image);

      oStream.writeTo(foStream);
   }


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

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

      Cipher cipher = Cipher.getInstance(algorithm);

      byte[] tmp = encrypt(loadImage(), cipher, publicKey);
      
      saveImage(tmp);

   }

   private static byte[] encrypt(byte[] 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);
      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();
   }
}

das eigentlich Problem ist, dass ich beim Aufruf von

Java:
 byte[] tmp = encrypt(loadImage(), cipher, publicKey);

ein leeres Array geliefert bekomme. Leider fehlt mir hier aber ein wenig das Basiswissen um selber auf den Fehler zu kommen.

Viele Dank euch schonmal

Sebastian
 
Schau doch mal, ob dein File überhaupt gefunden wird ;) (damit meine ich beide file's)
Kannste dir ja einfach was in die Konsole geben lassen(siehe Code) oder du behandelst Exceptions

Java:
if(file.exists() && file.canRead() )
    System.out.println("gefunden und lesbar");
 
Zuletzt bearbeitet:
Hi,

das war auch mein erster Gedanke aber beim Aufruf von

Java:
saveImage(loadImage)

wird das Bild korrekt kopiert. Die Kopie ist zwar ein KB kleiner aber das sollte mich nicht weiter stören ;)

hier nochmal der Orginalpost von Thomas, den ich ein wenig verändert habe:

http://www.tutorials.de/java/212543-verschluesselung-2.html#post1370684

das einzige was ich verändert habe ist die Signatur von encrypt und den darin enthaltene Aufruf von cos.write(...)

Gruß

Sebastian
 
Hi.

Irgendwie machst du dir aber doppelte Arbeit: du liest ein JPEG mit ImageIO, kreierst dann ein ByteArrayOutputStream und schreibst dann da ein als JPEG gerendertes Bild rein. Warum benutzt du denn nicht gleich die Daten aus der Datei?

Der Fehler liegt bei der Wahl des Ciphers. SUN's / Oracles RSA Implementierung verschlüsselt max. einen ganzen Block und tut offenbar einfach *nichts* (sprich: wirft keine Exception) wenn die Daten zu groß sind (also nicht in den Block passen).

Siehe z.B. http://www.ureader.de/message/629570.aspx

Gruß
 
So, ich roll den Thread hier bewusst noch mal auf, um endlich mal ne Lösung für die Probleme zu geben.

In den Jahren 2005 , 2007 , 2008 und 2010 wurden immer wieder die selben Fehler gemacht :

erstens : bei den asynchronen KeyPairGeneratoren muss man auf das initialisieren achten. Es reicht nicht nur ein KeyPairGenerator.getInstance aufzurufen, mann muss diese dann auch noch richtig initialisieren mit KeyPairGenerator.initialize

zweistens : egal für welchen Modus, Cipher müssen ebenfalls initialisiert werden. Das geht mit Cipher.init Natürlich vorher über Cipher.getInstance erstmal ne Instanz holen.

drittens : SUN's RSA-Provider kann nur maximal 128 Byte, also die 1024bit Schlüssellänge, an einem Stück verschlüsseln. Alles was drüber geht wird entweder verworfen oder bei entsprechendem init als Blockverschlüsselung verarbeitet.

viertens : RSA ist nicht dafür gedacht größere Daten zu verschlüsseln. Es wird in der regel nur für den sicheren Austausch eines symetrischen Schlüssels verwendet.

fünftens : in Bezug auf den Thread 212543, welcher hier erwähnt wurde, möchte ich nachträglich darauf hinweisen : ja, es ist richtig das RSA und AES und auch die meisten anderen Cryptoverfahren auf mathematischen Rechnungen beruhen. Aber wie der Rechner die Kombination der Massen an Bits als ZAHLEN darstellt sollte man der Implementierung überlassen. Das alles selbst zu implementieren dürfte selbst nach RFC verdammt schwierig und umfangreich werden. Man sollte einfach fertige Frameworks wie die SUN Implementierung oder BouncyCastle verwenden.


Zum Thema des "BILD"-verschlüsselns :

Es ist nichts anderes als das Verschlüsseln einer Datei.
Wobei es grade bei multimedia-Dateien *Bilder, Musik, Video* mehrere Arten von Verschlüsselungen gibt.
Bei Bildern z.b. kannst du entweder die Datei normal verschlüsseln und hast dann "Datensalat" oder du machst dir die Mühe das Bild auch als solches einzulesen, dir die Graphic-Informationen holen, diese zu verschlüsseln und dann wieder als Bild abzuspeichern. So würde dann z.B. aus einem schwarzen Bild ein buntes werden. Das Ganze ist leider komplizierte als es sich so einfach anhört, aber ich denke das es möglich sein sollte mit ImagIO was auf die Reihe zu bekommen.
Analog gilt das selbe für Audio und Video

Ein fertiges Hybrid-Krypto-System findet ihr hier
http://www.java-forum.org/allgemeine-java-themen/112839-netzwerk-sicherheit-hybrid-kryptosystem.html
Das Ganze ist nicht auf die Verwendung über Netzwerk beschränkt. Einfach eine caster-Klasse drum bauen die die Streams in Dateien umleitet. Und eine Erweiterung der asynccrypt.java um eine Methode zum Speichern des private-Keys. Und schon kann man das Ganze auch zur Dateiverschlüsselung verwenden.
Werde bei Gelegenheit mal was entsprechdenes zusammenbauen.
 
Zuletzt bearbeitet von einem Moderator:
Hi.

Wenn du das jetzt noch in eine ordentliche Form bringst (Groß-/Kleinschreibung, Satzzeichen, Absätze etc. -- siehe Netiquette(!)) würde sich das evtl. auch jemand durchlesen.

Gruß
 
Zuletzt bearbeitet:
hab ich gemacht wie du sehen solltest
aber was die netiquette angeht ist dein nick auch sehr zwiespältig
aber ich denke das du das schon selbst weist
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück