Fließtext verschluesseln

Maddimini

Mitglied
Hallo :),

ich habe eine Implementiereung von RSA gemacht und dazu eine GUI erstellt. Leider kann ich mit meinem Code nur Zahlen verschlüsseln. Ich möchte aber gerne einen Text verschluesseln, wie zB
einen String "Das ist eine geheime Nachricht."
Also muss ich dafür den String in Teile zerlegen, die in ein Array speichern und dann bearbeiten?
Das Ergebnis ist dann aber nicht wieder entschluesselbar :(

Wie kann ich das anstellen?

Vielen Dank schoneinmal! :)
 
Ein String lässt sich in Characters und ein Character in ein Integer konvertieren . Umgekehrt lässt sich ein Integer in ein Character konvertieren und zu einem String zusammensetzen. Wo ist das Problem?
 
Zuletzt bearbeitet:
hier der Code:
Java:
import java.math.BigInteger;
import java.util.Random;

public class RSAone
{
    BigInteger p,q;  // Primzahlen
    BigInteger n;    // n = p * q
    BigInteger phin; // Eulersche Phi-Funktion
    BigInteger e;    // beliebig mit ggT(e,phi(n))=1 und 1<e<phi(n)
    BigInteger d;    // multiplikativ Inverses zu e bzgl. phi(n)
    
    
    public RSAone()
    {
        // rsa_setup von Hand aufrufen
    }
    
    public void rsa_setup()
    {
        rsa_setup(100);     
    }
        
    public void rsa_setup(int bitLength)
    {
        Random rnd = new Random();
        
        p = BigInteger.probablePrime(bitLength, rnd); 
        q = BigInteger.probablePrime(bitLength, rnd); 
        
        n = p.multiply(q);
        
        phin = p.subtract(BigInteger.ONE).multiply( (q.subtract(BigInteger.ONE)) );
        
        e = new BigInteger(phin.bitLength(), rnd); 
        BigInteger[] xy = new BigInteger[2];
        BigInteger ggT;
        do 
        {
           e = new BigInteger(phin.bitLength(), rnd).add(BigInteger.ONE);  
           xy = erwEuklAlg(e, phin);
           ggT = (e.multiply(xy[0])).add(phin.multiply(xy[1])); 
        }
        while( !(ggT.equals(BigInteger.ONE) && e.compareTo(phin) == -1 && e.compareTo(BigInteger.ONE) == 1 ) );
        
        d = xy[0];
        
        while (d.compareTo(BigInteger.ZERO) < 0) {d = d.add(phin);}
        
    }
    
     /**
     * Erweiterter euklidischer Algorithmus
     */ 
    
    public BigInteger[] erwEuklAlg(BigInteger m, BigInteger n)
    {
        BigInteger[] xy = new BigInteger[2];
        BigInteger[] oldxy =  new BigInteger[2];
        BigInteger[] dr = new BigInteger[2];
        
        dr = n.divideAndRemainder(m);
        
        if (dr[1].equals(BigInteger.ZERO))
        {
           xy[0] = BigInteger.ONE;
           xy[1] = BigInteger.ZERO;
        }
        else
        {
            oldxy = erwEuklAlg(dr[1],m);
            xy[0] = oldxy[1].subtract(oldxy[0].multiply(dr[0]));
            xy[1] = oldxy[0];
        }
        return xy;
    }
    
    /**
     * binaere modulare Exponentiation
     */
    
    
    public BigInteger bme_1(BigInteger geheimText, BigInteger e, BigInteger m)
    {
        e =d;
        return bme(geheimText,  e,  n);
    }
    
    public BigInteger bme(BigInteger b, BigInteger e, BigInteger m)
    {
        BigInteger two = new BigInteger("2"); // Erzeugung einer BigInteger-Konstanten 2.
        BigInteger r = BigInteger.ONE;
        BigInteger p = b;
        BigInteger[] dr = new BigInteger[2];
        
        while (e.compareTo(BigInteger.ZERO) == 1)
        {
            dr = e.divideAndRemainder(two);
            if (!(dr[1].equals(BigInteger.ZERO))) 
            {    
                r = r.multiply(p).mod(m);
            }
            p = p.multiply(p).mod(m);
            e = dr[0];
        }
        
        return r;
    }
    
    /**
     * RSA-Verschluesselung
     */
    
    public BigInteger encrypt(BigInteger y)
    {
        if (y.compareTo(n) == 1) 
        {
            System.out.println("Die Klartext-Zahl muss kleiner n sein!");
            return y;
        }
        else
        {
            return bme(y,e,n);
        }     
    }    
      
    /**
     * RSA-Entschluesselung
     */
    
    public BigInteger decrypt(BigInteger y)
    {
         return bme(y,d,n);        
    }
        
    // Methode, die einen int-Wert in einen BitInteger umwandelt
    public BigInteger int2big(int x)
    {
        return new BigInteger((new Integer(x)).toString());
    }
    
}

Jetzt würde ich gerne irgendwie einen eingelesenen String durch einen BigInteger ausdrücken, den dan verschlüsseln und am Ende wieder entschlüsseln :/
 
Wow ... also das sich jemand den Aufwand macht und RSA selbst implementiert ist schon eine gute Leistung.
Auch bin ich persönlich von deiner Implementierung des erweiterten euklidischen Algorythmus beeindruckt.
Wobei ich dir gleich hier mal den Wind aus den Segeln deiner Begeisterung nehmen muss ...

Java stellt mit der Methode BigInteger.modInverse(BigInteger) eine sehr einfache Variante dessen bereit.
Wenn wir mal das Beispiel von Wikipedia http://de.wikipedia.org/wiki/RSA-Kryptosystem nehmen und für e=23 und phi(N)=120 annehmen so erhalten wir mit
Java:
BigInteger d=(new BigInteger("23")).modInverse(new BigInteger("120"))
für d=47 ... was dem Beispiel auf Wikipedia entspricht.

Auch im weiteren Verlauf deines Codes sieht man das du dir die Doc zu BigInteger nicht richtig durchgelesen hast ... denn für BigInteger.multiply(BigInteger).mod(BigInteger) stellt Java auch hier wieder eine vereinfachte Methode bereit : BigInteger.modPow(BigInteger, BigInteger).

Du siehst also das man deinen Code um einiges kürzen und dadurch übersichtlicher machen kann.

Wenn das ganze allerdings als Matheübung fungieren soll bin ich von der Leistung beeindruckt und verstehe dieses für mich sehr Umständliche coding.

Dann ist weiterzusagen : RSA ist nicht für die Verschlüsselung selbst gedacht !
RSA ist kein Block-Cipher ... es ist damit also nur über Umwege möglich Informationen die Länger als die Schlüssellänge sind zu verschlüsseln.
In der Praxis wird hier ein Hybridverfahren eingesetzt : RSA+AES
Wobei RSA lediglich für den sicheren Austausch des AES Schlüssels verwendet wird *AES hat drei verschiedene Schlüssellängen : 128Bit , 192Bit , 256Bit ... der zugrundeliegende Rjindae-Algorythmus hat zu dem noch eine Variable Blocklänge von 128Bit , 192Bit , 256Bit ... von der aber in AES nur die Blocklänge von 128Bit übernommen wurde *Quelle : ebenfalls Wikipedia**
Somit passt ein AES Schlüssel also auf jeden Fall in die Schlüssellänge von RSA *bei RSA sollte mindestens eine Schlüssellänge von 1024Bit verwendet werden ... mitlerweile wurde aber diese Empfehlung aus Sicherheitsgründen auf 2048Bit angehoben*.

Das aber nur am Rande als Zusatzinformationen zum Thema RSA und Verschlüsselung damit.

Zu deinem eigentlichen Problem ...
Deine Implementierung ist soweit das du damit Zahlen verschlüsseln kannst *bei einer Länge der Primzahlen von jeweils 100Bit sollte die Schlüssellänge je nach Input zwischen 150Bit und 200Bit betragen ... womit die Mindestlänge von 256Bit für RSA noch nicht mal erreicht wird*.
Nun willst du aber auch andere Informationen als "nur Zahlen" verschlüsseln.

Um das zu erreichen musst du also erstmal diese Informationen in Zahlen umwandeln. Das geht am einfachsten mit den in Java eingebauten mitteln : String.getBytes(). Damit erhälts du ein Byte-Array. Mit diesem Byte-Array kannst du jetzt "rechnen". Ein Byte kann nur einen Wer zwischen -128 und +127 *oder 0 bis 255* haben.
Jetzt kannst du aus diesem Byte-Array einen BigInteger erzeugen : new BigInteger(byte[]) und mit diesem weiter arbeiten.

Wie du die Informationen des verschlüsselten BigInteger darstellst ist dir überlassen ... wichtig ist nur das nach dem übertragen über irgend einen Weg *meistens eine Socket-Verbindung* beim Empfänger aus deiner selbst gewählten Darstellung auch wieder genau dasselbe BigInteger-Objekt erzeugt werden kann wie es beim Absender vorhanden war. Dazu bietet sich BigInteger.toString(int) an mit dem du einen BigInteger bequem in einen Hex-String umwandeln kannst und beim Empfänger mit new BigInteger(String, int) wieder einliest *dazu setzt du für den int den Wert 16 *Hex**.

Nach dem du dann also aus dem Cipher-BigInt wieder den Plain-Text hast kannst du dir mit BigInteger.toByteArray() das Byte-Array besorgen was du beim verschlüsseln als Input verwendet hast. Daraus erzeugst du dann mit new String(byte[]) wieder einen String in dem nun dein ursprünglicher Plain-Text stehen sollte.

Hört sich alles etwas kompliziert an ... sollte aber für dich der den erweitereten euklidischen Algorythmus implementiert hat keine Schwierigkeit sein.

Ich poste dir bewusst keinen Source da ich dir nur den Denkanstoß geben wollte wie du es umsetzen könntest.

Vielleicht noch als kleines Basic am Rand : ein Rechner stellt ALLE Informationen grundsätzlich als Zahlen dar ... also kannst du grundsätzlich auch mit ALLEN Infromationen solche Rechenoperationen durchführen ... du musst nur dafür sorgen das die Informationen im richtigen Format vorliegen.

Falls du interesse an einem ausgereiften RSA-AES-Hybrid-Kryptosystem hast welches die Java-API nutzt *und dadurch wesentlich sauberer und performanter ist* kannst du dir meine Implementierung in meinm Blog zu gemüte führen.
 
Zurück