Probleme mit String Byte[] und Unicode

  • Themenstarter Themenstarter Ishildur(NoPwd)
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
I

Ishildur(NoPwd)

Gast
Hallo zusammen, ich habe folgendes Problem:

1. Wie kann ich einen String in ein Byte - Array umwandeln?
2. Wenn ich einen Text mit dem Schlüssel "Charlie(JAVA&UNICODE)" chiffrieren will und mit dem Schlüsseln "Charlie(C++/ANSI)" dechiffrieren will, bekomme ich ein riesen Problem, da ja UNICODE 2 Bytes/char benötigt und dazu noch völlig andere Binärwerte repräsentieren, als der ANSI Zeichensatz! Wie löst man dieses Problem?

Gruss Ishildur
 
zu 1.: Indem Du die Augen aufmachst: java.lang.String.getBytes(String charsetName).
2. Die Zeichensätze müssen einfach kompatibel zueinander sein (siehe 1.). Aber Chiffrieren? Meinst Du nicht (De-)Kodieren? Bevor Du mit Kryptisierung oder so kommst, solltest Du zunächst mit den Grundlagen (hier: Zeichensätze) fertig werden. 😉

MfG
Ark
 
Bevor Du mit Kryptisierung oder so kommst, solltest Du zunächst mit den Grundlagen (hier: Zeichensätze) fertig werden. icon_wink.gif
Ja, da hast du natürlich Recht?

Ich habe eine Rijndael Verschlüsselung in C++ geschrieben und habe nun mühe, diese nach Java zu portieren, weil ich natürlich den Schlüssel, den ich im C++ Programm zum chiffrieren eingebe, nicht einfach in JAVA zum dechiffrieren verwenden kann, da JAVA einen anderen Zeichensatz verwendet! Gibts vielleicht eine Möglichkeit, in JAVA UNICODE in ANSI umzuwandeln?

Lg Ishildur
 
ja, ganze einfach... wenn du nichts findest (was ich schwer bezweifle) map einfach die aciis auf unicode... bau deinen eigenen zeichensatz ;-). um weitere verwirrung zu stiften. ich habe gehört, dass java tiger mehr als 2 bytes für einen buchstaben verwendet ;-) unicode 4 (oder wars 3?)...
 
Hey, kann es sein, dass Java unter MIDP2.0 nur 1 Byte pro character benötigt? Ist dies dann auf allen Handys so?
 
Ich verstehe keinen Ton (mehr).

Wo genau ist jetzt das Problem? Was läuft verkehrt? Wenn Du bis jetzt Probleme hast, dann musst Du uns schon mit Informationen zustopfen. Wir brauchen z. B. den Quelltext, die Ausgabe dieses Programms und ein Beispiel, wie es (von der Ausgabe her) hätte aussehen müssen.

MfG
Ark
 
OK OK, gaaanz ruhig, das kriegen wir schon hin!

Stell dir vor, ich muss in einer TextBox ein 128-Bit Chiffrierungsschlüssel definieren.
Wenn nun jedes Zeichen 2 Bytes benötigt, dann müssen 8 Zeichen definiert werden, weil 8 Zeichen * 2 Byte = 16 Byte = 128-Bit. Wenn nun aber jedes Zeichen nur ein Byte benötigt, wie bspw. bei einem Programm, das in C++ geschrieben wurde, dann müssen 16 Zeichen definiert werden, weil 8 Zeichen * 1 Byte = 16 Byte = 128-Bit.

Wenn ich nun den Chiffrierschlüssel "r2d2c3po05j1982k" in C++ definiere und den Text so chiffriere, dann kann ich diesen Text in Java nicht mehr so einfach dechiffrieren, weil der Benutzer schon mal das Kennwort nicht mehr eingeben kann. Er muss dann irgendwas völlig anderes eingeben, damit die Binärrepräsentation dieses Strings indentische ist.
Das gleiche Problem hätte ich, wenn es theoretisch möglich währe, weniger Zeichen zu definieren, weil bspw. das Zeichen 'a' in UNICODE eine andere Binärrepräsentation hat als in ANSI.

Oder anders ausgedrückt: bspw.

ANSI 'ab' = 01000110|10101101 = 2 * 1 Byte
UNICODE 'k' = 0100011010101101 = 2 Bytes

Das sind zufällige Werte, war zu faul, tatsächliche Werte zu ermitteln, aber das Problem sollte klar sein!


Ich habe da noch ein weiteres Problem:

Code:
   // loop for walking each row of the affine transformation matrix wich must be
   // multiplicated by the multiplicative inverse of the current value in the s-box
   for(byte k=0;k<8;++k){
    // computate the current row of the affine transformation matrix wich is
    // constructed from the value 0x8f by default
    byte row = (byte)((this.genTrm >>> k) | (this.genTrm << (0x08 - k)));
    
    System.out.println(Integer.toBinaryString(row & 0xff));
    
    // start a loop for walking each bit of the current row
    for(byte l=0;l<8;++l){
     // check if both bits are set
     if((row & (0x80 >> l)) != 0x00 && (inv & (0x01 << l)) != 0x00)
      // invert the current bit at the current position in the current value of the s-box
      this.sBox[i] ^= (0x01 << k);
    }
   }

Die Zeile
Code:
byte row = (byte)((this.genTrm >>> k) | (this.genTrm << (0x08 - k)));

sollte folgende Transformationsmatrix generieren:
10001111
11000111
11100011
11110001
11111000
01111100
00111110
00011111

Stattdessen generiert Sie folgende Matrix:
Code:
10001111
11000111
11100011
11110001
11111000
11111100
11111110
11111111

Mit anderen Worten, bei der bitweisen Rechtsverschiebung wird ein 1 anstatt ein 0 nachgeschleppt. Ich habe das darauf gedeutet, dass SUUUUPEEER Java nur signed Werte verwendet und der Wert HEX 0x8f oder DEZ 243 höher als 128 und somit eine negative Zahl repräsentiert, was sich in der Binärdarstellung so auswirkt, dass einfach alle sbits mit 1sen gefüllt werden. also 2 = 00000010; -1 = 11111110

Offenbar haben die Entwickler von Java an die damit verbundenen Problemchen gedacht und den >>> Operator eingeführt. Nur leider zeigt der überhaupt keine Wirkung! Es werden immer noch 1sen anstatt 0len auf der linken Seite nachgezogen, wenn ich eine bitweise Rechtverschiebung mache...

Was mache ich also falsch??

Lg Ishildur
 
Versuch's mal mit:
Code:
String s="Hallo!";
Charset charset = Charset.forName("US-ASCII");
byte[] b = s.getBytes(charset)
Welche Charsets unterstützt werden steht in der Klasse Charset.
 
bei >>> wird wirklich eine 0 von links geschoben,
allerdings werden vorher die bytes nach int konvertiert, also sind sowieso erst mal 24 Bits links 1, du musstest 24x >>> schieben, damit die erste 0 zu sehen ist,

teste
row = (byte) (b >>> 24+k);

-------

eine Lösung für bytes wäre evtl. folgendes
row = (byte) (((b & 0xFF) >> k) | (b << (0x08 - k)));

da wird b erst in ein int gewandelt und die ersten 24 Bits auf 0 gesetzt,

da das dann sowieso eine positive Zahl ist, kannst du >> oder auch >>> verwenden,
in beiden Fällen wird eine 0 eingefügt, bzw. es wäre auch egal was ganz links eingefügt wird, da sind ja 24 Nullen als Puffer
 
Bei der Shiftoperation wird erst mal in int konvertiert?
OK, das erklährt eigentlich alles? Schade, wenn man dies nicht weiss!

Danke vielmals, damit wäre das Problem gelöst!
 
Hey, habe da noch sowas entdeckt, worauf ich mich langsam ein wenig fragen muss:

Code:
byte a = 5;
byte b = 10;
byte c = a+b; // possible loss of precision, found: int required: byte

Was soll denn das jetzt? :?
Boxt Java etwas jeden Datentype bei jeder Operation in einen Int um? ???:L Wofür benötigt man dann überhaupt noch die anderen Datentypen? Wieso gibts nicht nur noch int, float, char und fertig? :bae:

Also wirklich jetzt... :bahnhof:
 
Der Loss-of-precision wird wohl eher in den Zeilen 2 und 3 auftauchen...
 
Das Problem ist, dass er Compiler in deinem Fall vermutet, dass die Summe zweier Bytes evtl. nicht mehr als ein Byte darstellbar ist; der Compiler analysiert den Code nicht soweit, dass er erkennen könnte, dass das in diesem Fall nicht passieren kann.

Probier mal
Code:
		final byte a = 5;
		final byte b = 10;
		byte c = a+b;

Durch die Angabe von final kann der Compiler die beiden Variablen als Konstanten betrachten und direkt in den unteren Ausdruck einsetzen; dabei kann er auch erkennen, dass kein Überlauf möglich ist.

Die Variante
Code:
		final byte a = 5;
		final byte b = 127;
		byte c = a+b;
führt dann auch wieder zu einem Fehler, weil hier in jedem Fall ein Überlauf eintreten wird.
 
aber beim Addieren zweier int-Zahlen wird doch auch nicht nach long konvertiert, nur weil theoretisch ein Überlauf stattfinden kann?
ich verstehe das von Java auch nicht

und die Addition zweier final-Variablen macht ja nur sehr selten Sinn,
dann entweder direkt addieren oder das (byte) ist kürzer als die beiden final
 
Komisch:

Bei mir gibt der Compiler im 2. Fall nicht nur 'ne Warnung, sondern gleich einen Fehler: 'cannot convert from int to byte'.

Aber was solls... man kann das ja auch so schreiben:
Code:
byte c = (byte) (a + b);
so kommt natürlich ein negativer Wert für c raus.

Ich kann mich erinnern, das es hier Eingangs um die Konvertierung von 'char' nach 'ASCII' ging. Das sollte meines Wissens ungefähr so gehen.
Code:
char c = 'A'; // beliebige ASCII Zeichen (0 - 127 bzw. 0 - 255 wenn Charset = ISO-8859-1)
byte b = (byte) (c & 0xFF);
ein ByteArray bekommt man nun so:
Code:
String tmp = "TestString";
tmp += '\u00ff'; // test machen
byte[] buffer = tmp.getBytes(Charset.forName("ISO-8859-1"));
Das letzte Byte in 'buffer' müsste den Wert -1 haben. mit negativen Werten lässt sich aber kaum über Arrays iterieren. Deswegen mus in Java wiedermal ein breiterer Primitivtyp (int bietet sich an) verwendet werden.
Code:
byte index = -128; // 0x80
byte code = buffer[(int) index & 0xFF];

mfg 0x0badc0de
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben