| 

.NET C# Java Javascript Exception

1
Hallo,

die nachfolgende Methode, die in C geschrieben ist, wollte ich nach C# übersetzen. Es handelt sich dabei um "Raiden-Cipher" (http://raiden-cipher.sourceforge.net/).

void raiden(unsigned long *data,unsigned long *result,unsigned long *key)
{

unsigned long b0=data[0], b1=data[1],i,k[4]={key[0],key[1],key[2],key[3]}, sk;
for(i=0; i< 16; i++)
{
sk=k[i%4]=((k[0]+k[1])+((k[2]+k[3])^(k[0]<<k[2])));
b0 +=((sk+b1)<<9)^((sk-b1)^((sk+b1)>>14));
b1 +=((sk+b0)<<9)^((sk-b0)^((sk+b0)>>14));
}
result[0]=b0;
result[1]=b1;
}


Mein Übersetzungsversuch sieht so aus:

private void raiden(uint[] data, uint[] result, uint[] key)
{
uint b0 = data[0];
uint b1 = data[1];
uint i;
uint[] k = {key[0],key[1],key[2],key[3]};
uint sk;
for(i = 0; i< 16; i++)
{
sk = k[i%4] = ((k[0]+k[1])+((k[2]+k[3])^(uint)(k[0]<<(int)k[2])));
b0 += ((sk+b1)<<9)^((sk-b1)^((sk+b1)>>14));
b1 += ((sk+b0)<<9)^((sk-b0)^((sk+b0)>>14));
}
result[0]=b0;
result[1]=b1;
}


In meinem Versuch habe ich die Zeile, die von meinem Compiler als Grund für einen Überlauf benannt wurde, fett dargestellt. Ich vermute den Fehler am Ende der betreffenden Zeile. Könnte ich den dortigen Shift falsch umgesetzt haben? Jede Hilfe für das Problem ist willkommen.
13.10.2011
Mond 11 2
Jens Duczmal 2,6k 1 3 9
3
Auf ursprüngliche Frage zurückgesetzt.
Jens Duczmal 16.10.2011
2 Antworten
2
Wenn Du den uint k[2] auf int castest, kann es zu einem Überlauf kommen, wenn k[2] größer ist als int.MaxValue. Da Du aber ohnehin nur die untersten 5 Bit brauchst, kannst Du, wie in diesem Thread vorgeschlagen, modulo 32 rechnen, also (ungetestet):

k[0]<<(int)(k[2]%32)


Update:
Damit ein solcher Cast eine OverflowException auslöst, muss der Code in einem "checked Kontext" laufen. Zitat MSDN:
Damit die Arithmetik-, Umwandlungs- oder Konvertierungsoperation eine OverflowException auslöst, muss die Operation in einem überprüften Kontext auftreten. Standardmäßig werden arithmetische Operationen und Überläufe in Visual Basic überprüft; in C# erfolgt keine Überprüfung. Wenn die Operation in einem nicht überprüften Kontext auftritt, wird das Ergebnis abgeschnitten, indem alle höherwertigen Bits ignoriert werden, die nicht in den Zieltyp passen.

D.h. Dein Code läuft offenbar entweder innerhalb eines "checked {...}"-Blocks, oder in den Projektoptionen (Erstellen -> Erweitert) ist das Häkchen bei der Option gesetzt, auf arithmetischen Unter-/Überlauf zu prüfen.

Da Du angibst, dass die Entschärfung des Casts nichts gebracht hat, bleiben als andere Fehlerquelle nur die Additionen. Eine uint-Addition ergibt in C nie einen Überlauf, in C# hingegen schon, wenn es sich um einen checked-Kontext handelt. Ist das Ergebnis zu groß, wird es verkleinert - siehe dazu hier bei stackoverflow. Auf den ersten Blick scheint mir, dass der dazu verwendete Algorithmus das gleiche bewirkt wie das Verhalten in C# in einem unchecked-Kontext (von einem uint die obersten Bits wegschneiden müßte odch das gleich sein wie modulo uint.MaxValue zu rechnen, oder?). D.h. Du könntest dann den Code dadurch zum Laufen bringen, dass Du den Block mit unchecked klammerst.
13.10.2011
Matthias Hlawatsch 13,2k 4 9
Damit ist das Problem leider auch nicht weg!
Mond 13.10.2011
Dann wird vermutlich eine der Additionen den Überlauf verursachen. Die Summe von zwei uints kann ja größer sein als uint.MaxValue. Setz doch mal einen Breakpoint auf die Zeile, schau Dir die einzelnen Werte von k[i] an und laß Dir im Direkt-Fenster die einzelnen Teilterme ausrechnen.
An dem Shift selbst kann ich nichts verdächtiges entdecken, und soweit ich weiß löst ein Shift auch niemals einen Überlauf aus.
Matthias Hlawatsch 14.10.2011
Aber wenn alle Datentypen richtig angewendet wurden, kann es nicht zu Überläufen kommen - es sei denn, im C-Code würde ein Fehler sein. Am Wochenende werde ich mal meinen alten C-Compiler ausbuddeln und den C-Code nachbauen und die Ergebnisse mit den von C# vergleichen.
Mond 14.10.2011
Zu Überläufen kann es schon kommen - 2*uint.MaxValue passt nicht mehr in einen uint, in C genausowenig wie in C#. Aber es gibt ein definertes Verhalten für diesen Fall (Verkleinern des Ergebnisses). Was mich zu der Frage führt: was genau meinst Du mit "die von meinem Compiler als Grund für einen Überlauf benannt wurde". Welche Meldung gibt denn der >Compiler< aus? Hatte offen gestanden schlecht gelesen und eine OverflowException angenommen, aber die käme ja nicht vom Compiler.
Matthias Hlawatsch 14.10.2011
@Matthias: Ich glaube er meint auch eher den Debugger als den Compiler :)

Es könnte glaube ich auch helfen, alle Werte dieser zwar dadurch platzsparenden aber dadurch schwer zu debuggenden Zeilen in Einzelschritten zwischenzuspeichern.
So kann man viel besser die Ergebnisse der einzelnen Operationen debuggen und findet auch schneller die Operation, die den Fehler verursacht: Die Zeile, wo der Debugger stecken bleibt/rummeckert.
Außerdem, ich weiss dass C's unsigned long dem C# uint entsprecht, aber man kann ja mal versuchen, UInt64 (ulong) zu nutzen :)
Karill Endusa 14.10.2011
@Karill Ich hatte auch erst gedacht, es wäre der Debugger. Aber inzwischen hab ich mal ein bißchen herumgespielt mit den Überläufen und festgestellt, dass es da zwar zu einem Informationsverlust kommt, aber keine Exception fliegt.
Matthias Hlawatsch 14.10.2011
Akso, wenn ich mich bei der Fehlermeldung falsch ausgedrückt haben sollte, das hier kam als Meldung:

Unbehandelte Ausnahme vom Typ System OverflowExeption Die Opertion hat einen Überlauf verursacht
Mond 14.10.2011
Siehe das Update meiner Antwort.
Matthias Hlawatsch 14.10.2011
Informationsverluste sind wohl zu erwarten - aber wohl auch gewollt, was lediglich die Problemzeile betrifft. Welcher von den 4 zur Verfügung stehenden Sub-Keys verwendet wird, wird durch die Abwicklung hinter dem ersten = Zeichen ermittelt. Die eigentlichen Daten werden erst anschließend mit b1 und b0 behandelt. Hier darf es keine Verluste geben. Wichtig hingegen ist es, daß der C#-Code den results vom C-Code entspricht.
Mond 14.10.2011
@Matthias Hlawatsch, dein Update ist prima, wenn man den Code in Zeitlupe ausführen will. Etwas mehr Professionalität wäre da schon erwünscht. Um eine Festplatte damit zu verschlüsseln brauche ich damit 7 Tage.
Mond 15.10.2011
1
@Mond Habe ich etwa behauptet, professioneller Hellseher zu sein? Du hast gefragt, warum es in der markierten Zeile einen Überlauf gibt. Von Performance war keine Rede. Du bekommst hier Hilfe kostenlos und ohne, dass einer der Antwortenden Dir zu irgendetwas verpflichtet wäre. Du hast in Deiner Frage außerdem selbst geschrieben, dass jede Hilfe willkommen sei. Der unverschämte Ton Deines letzten Kommentars steht dazu in krassem Widerspruch.
Matthias Hlawatsch 17.10.2011
0
Hi Mond,

alle hier getätigten sog. Hilfestellungen sind Schrott! Entweder sie können nicht helfen, oder sie wollen nicht. Bring deine Frage woanders unter.

Falls du hier bleiben willst, werde ich mal über eine sinnvolle Lösung nachdenken. Das kann aber etwas dauern.

Dave V.
16.10.2011
Mond 11 2
War mir schon klar. Das hätte jetzt nicht sein müssen!
Mond 16.10.2011
3
Falls Du nicht unter multipler Schizophrenie leidest, sag mal Deinem kleinen Bruder, er soll die Finger von Deinem Account lassen und hier nicht vandalieren. :o)
Jens Duczmal 16.10.2011

Stelle deine .net-Frage jetzt!