# Problem mit Dateien/XOR-Verschlüsselung



## java75 (19. Jun 2006)

Hallo zusammen,
ich habe ein Problem mit einem Programm, das Dateien mit XOR verschlüsseln und entschlüsseln soll.

Als ersten Ansatz habe ich versucht, den zu verschlüsselnden Text in einen String zu schreiben und jedes Zeichen des Strings mit einem festen Wert zu XORen. 

Z. B. :

```
s=text;
a="";                       
for (int  h=0; h<textlen; h++ ) {
  int i = (int)s.charAt(h) ^ 248;
  a += (char)i;
}
```
Zum Entschlüsseln XOR mit dem gleichen Wert.

So funktioniert das einwandfrei, aber wenn ich den verschlüsselten Text in eine binäre Datei schreibe und vor dem Entschlüsseln wieder auslese, funktioniert es in diesem Fall nur, wenn der Wert mit dem ich XOR nehme, kleiner als 160 ist. Ab 160 scheint er nicht mehr korrekt in die Datei zu schreiben. Jedenfalls entsprechen nach dem Entschlüsseln nicht mehr alle Zeichen dem ursprünglichen Text.

Hat jemand eine Idee, woran das liegen kann?


----------



## 0xdeadbeef (19. Jun 2006)

Bei Konvertierungen von char und byte in int und umgekehrt muß man sehr aufpassen, weil Bytes vorzeichenbehaftet sind und alle Nicht-Integer-Typen bei sämtlichen Rechenoperationen automatisch in Integer konvertiert werden.

Beispiel: 


```
byte b = 0x80;  // eigentlich +128, aber vorzeichenbehaftet interpretiert -128
int i = b;           // i ist -128 statt +128
int j = b & 0xff; // j ist +128
```

Daß die Grenze jetzt bei Dir woanders liegt, hängt vermutlich mit dem XOR zusammen.

Nebenbei bemerkt: selbst mit einem längeren Schlüssel wird der so erzeugte Code in Sekunden entschlüsselbar sein, weil der Schlüssel durch die im Regelfall "leeren" High-Bytes im Klartext auslesbar ist. Hatten wird hier schon mal irgendwann.


----------



## java75 (20. Jun 2006)

Ah, danke für den Tip, das bringt mich dem Problem schon etwas näher...
ich habe noch eine Kleinigkeit verändert, und zwar:


```
s=text;
byte[] ascii=s.getBytes();
a="";                       
for (int  h=0; h<textlen; h++ ) {
  int i = (int)ascii[h] ^ 248;
  a += (char)i;
}
```

Zunächst habe ich versucht, mit "getBytes" den ASCII-Code der Zeichen in s zu bekommen- ungefähr wie "java opfer" in diesem Forum.
Jetzt geht es wirklich nur noch mit Werten bis 127- mehr Elemente hat ja auch die ASCII-Tabelle nicht.

Merkwürdigerweise funktioniert es immer noch mit größeren Werten, wenn ich nicht in eine Datei schreibe, sondern sofort decodiere...

Ich sollte mein Problem nochmal genauer schildern: 
ich suche nach eine Lösung, den ASCII-Code der Zeichen eines Textes zu bekommen, zu XORen(mit Werten bis 255) und wieder in Zeichen umzuwandeln. Das sollte doch auch in Java irgendwie machbar sein...

in Basic funktioniert es beispielsweise so:

```
I = Asc(Z1) Xor K(L)
A = A + Chr$(I)
```

Ich wäre sehr dankbar für jede Hilfe.


----------



## 0xdeadbeef (20. Jun 2006)

Wie oben erläutert, ergibt folgender Code Unsinn:


```
int i = (int)ascii[h] ^ 248;
```

Der Int-Cast bewirkt hier gar nichts, denn das Byte auf der linken Seite wird sowieso automatisch nach Int gecasted, bevor Java damit die XOR-Operation angeht. Und genau hier liegt wie gesagt das Problem, weil das höchste Bit des Bytes als Vorzeichen interpretiert wird. Alle Zeichen >=128 werden also (in diesem Fall) fälschlich als vorzeichzenbehaftet nach Int konvertiert.

Richtig wäre hier:

```
int i = (ascii[h] & 0xff) ^ 248;
```
Durch das "& 0xff" werden alle bei der Konvertierung hinzugekommenen oberen Bits wieder entfernt. Das Resultat ist eine vorzeichenlose 32bit-Zahl, bei der maximal die untersten 8bit ungleich Null sind.

Nochmal ein Beispiel:
Das Byte sei 192 bzw. 0xC0. Binär ist das 0b11000000. Das oberste Bit ist gesetzt, also erweitert Java das bei der Konvertierung zu int, indem alle "oberen" Bits mit 1 gefüllt werden:
0b11111111111111111111111111000000. 
Das ist die Integer-Repräsentation von "-64"

Wenn man diesen Wert wieder in ein Byte casten würde, wäre das Byte binär betrachtet wieder ok und genau das gleiche mach auch das "& 0xff" auf Ebene des Ints:
0b11111111111111111111111111000000 & 0xff -> 0b11000000


----------



## java75 (27. Jun 2006)

Hm, danke, so funktioniert es perfekt(zugegeben, ich hätte es auch nach der ersten Antwort schon testen können...)- immer noch aber nur, wenn ich nicht in eine Datei schreibe und daraus lese.

Ich vermute, dass das Problem mit Konvertierungen zusammenhängt, die vor dem Schreiben/nach dem Lesen in/aus eine(r) Datei passieren.

Kann mir jemand eine Möglichkeit nennen, die codierten Zeichen wirklich unverändert in eine binäre Datei zu schreiben und wieder daraus zu lesen? Danke!


----------



## java75 (28. Jun 2006)

Sieht aus, als hätte sich das Problem gelöst.

Ich habe die Integer-Werte jetzt in Bytes statt in Chars umgewandelt und in die Datei geschrieben.
Nur beim Entschlüsseln wandele ich die Ints weiterhin in Chars um. 
Mit meinem Beispieltext funktioniert es zumindest...


----------

