Integer Variable wie in C
Steffen
- javascript
Hallo,
wie ihr wisst, kann in C eine Integer Variable max. 32 Bit Zahlen speichern, also rund 4 Mrd. (unsigned).
Wenn man diese grenze Überschreitet, dann wird wieder von vorne "gezählt".
In JavaScript kann man aber in eine Variable locker Zahlen bis ca. 10 Mrd. speichern, bevor es diesen "überlauf" gibt.
Mein Problem ist, dass ein JavaScript genauso rechnen muss wie ein C Programm.
Dies habe ich gelöst indem ich mod 4294967296 (%4294967296) für die Berechnung benutze, dies funktioniert aber nicht einwandfrei.
Mein C Code implementiert xTEA: http://en.wikipedia.org/wiki/XTEA
#include<stdio.h>
int main(void) {
unsigned long v0=0x70e1225d, v1=0x6e4e7655, i;
unsigned long sum=0, delta=0x9E3779B9;
unsigned long k[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
printf(" v0 : v1 : sum\n");
for(i=0; i<32; i++) {
v0 = ( v0+(((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3])) )%4294967296;
sum = (sum+delta)%4294967296;
v1 = ( v1+(((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3])) )%4294967296;
printf("%02d: %11u : %11u : %11u \n",i,v0,v1,sum);
}
printf("\n\nErg: %x : %x\n",v0,v1);
return 0;
}
Der Testvektor wurde von Wikisource entnommen, und das Ergebnis stimmt soweit.
Das %4294967296 kann auch entfallen, nur zur Übersicht (JavaScript).
Jetzt der JavaScript:
<script language="JavaScript">
<!--
encrypt();
function encrypt()
{
var v0 = 0x70e1225d;
var v1 = 0x6e4e7655;
var sum=0, delta=0x9E3779B9, i;
var k = new Array(0x00000000,0x00000000,0x00000000,0x00000000);
document.write(" i : v0 : v1 : sum<br>");
for(i=0; i<32; i++) {
v0 = ( v0+(((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3])) )%4294967296;
sum = (sum+delta)%4294967296;
v1 = ( v1+(((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3])) )%4294967296;
document.write(i+":"+v0+" : "+v1+" : "+sum+"<br>");
}
}
//-->
</script>
Die sum wird richtig berechnet, nur es gibt einen Fehler bei v0 und v1, diese werden falsch berechnet.
Wodran liegt dies, und wie kann man es lösen?
Grüße
Steffen
Hi,
wie ihr wisst, kann in C eine Integer Variable max. 32 Bit Zahlen speichern, also rund 4 Mrd. (unsigned).
Ja? Also meines Wissens ist das nirgendwo festgelegt. Augenblick, ich schau nochmal in den Standard: nein, ist nicht. Du kannst es auch nicht selber exakt festlegen, laut Standard sind nur Mindestgrößen möglichen. Siehe "limits.h" und "stdint.h".
Wenn man diese grenze Überschreitet, dann wird wieder von vorne "gezählt".
In JavaScript kann man aber in eine Variable locker Zahlen bis ca. 10 Mrd. speichern, bevor es diesen "überlauf" gibt.
Peinlicherweise habe ich gerade kein ECMA-Papier zur Hand, glaube mich aber entsinnen zu können, das dies so auch nicht festgelegt ist. Bitte dringend um Korrektur, falls erforderlich.
Mein Problem ist, dass ein JavaScript genauso rechnen muss wie ein C Programm.
Dies habe ich gelöst indem ich mod 4294967296 (%4294967296) für die Berechnung benutze, dies funktioniert aber nicht einwandfrei.
Wenn es nicht einwandfrei funktioniert, hast Du es auch nicht gelöst.
*grummel*
;-)
Mein C Code implementiert xTEA:
Na, das sieht dann aber doch eher nach dem Wheeler/Needham aus, gelle? ;-)
[...]
Die sum wird richtig berechnet, nur es gibt einen Fehler bei v0 und v1, diese werden falsch berechnet.
Was bitte heißt "falsch berechnet"? Wenn Du das rausbekommen hast, weißt Du auch, was Du falsch gemacht hast. Geh' einfach mal die Rechnung da durch.
Wodran liegt dies, und wie kann man es lösen?
Du bist von falschen Voraussetzungen ausgegangen und hast die Shifts nicht ausreichend beachtet.
Wenn Du statt der arithmetischen Berechnungen die Bitschuppserei _vollständig_ durchziehst klappt's.
BTW: auf http://www.simonshepherd.supanet.com/tea.htm gibt's auch zwei schon fertige Javascriptvarianten. Schau doch einfach mal unverbindlich rein.
so short
Christoph Zurnieden
Hallo,
ich hab jetzt >> durch >>> ersetzt.
Zwar sieht die letzte Zeile immer noch anders aus (was mich verwirrt hat), aber:
Wenn man die Zahl wieder in Hexadezimal umwandelt, sieht man, dass das Ergebnis mehr als 32 Bit hat.
Wenn man die niederwertigsten 32 Bit benutzt, dann stimmt wieder alles soweit.
Grüße
Steffen
Hi,
ich hab jetzt >> durch >>> ersetzt.
Ja, das ist z.B. eine Möglichkeit.
Zwar sieht die letzte Zeile immer noch anders aus (was mich verwirrt hat), aber:
Wenn man die Zahl wieder in Hexadezimal umwandelt, sieht man, dass das Ergebnis mehr als 32 Bit hat.
Wenn man die niederwertigsten 32 Bit benutzt, dann stimmt wieder alles soweit.
Ah, er hat es!
Jetzt hast Du noch das Problem, das der C-Code immer noch nicht zum Javascriptcode paßt. Oder hast Du Dich in limits.h und stdint.h eingearbeitet und den C-Code entsprechend repariert? Dann bitte ich um Entschuldigung.
so short
Christoph Zurnieden
Hallo,
also der C-Code passte von anfang an (laut Testvektoren).
Das umständliche %4Mrd etc. war nur damit ich den gleichen Effekt bei JavaScript erhalten (überlauf).
Was beim C Programm sowieso entfallen kann, sofern man keine 16/64 Bit Plattform benutzt.
Das ist aber jetzt nicht mehr nötigt, so das ich den schlanker, von Wikipedia stammen Quellcode benutzen kann.
Naja bei JavaScript lag es nur daran, dass ein Integer Variable mehr als 32 Bit (auf dem gleichen Prozessor) speichern kann.
Wenn man aber nur die letzten 32 Bit betrachtet, läuft der Script so wie der C-Programm.
Manchmal sollte man sich die Ausgabe doch Hexadezimal anstatt Integer sein, würde viel Zeit ersparen ^^.
Grüße
Steffen.
Hi,
also der C-Code passte von anfang an (laut Testvektoren).
Aber nur auf PC-Hardware.
Das umständliche %4Mrd etc. war nur damit ich den gleichen Effekt bei JavaScript erhalten (überlauf).
Aber nur auf PC-Hardware.
Was beim C Programm sowieso entfallen kann, sofern man keine 16/64 Bit Plattform benutzt.
Oder andere als 2s-Complement Little Endian Hardware, z.B. Embededware.
Das ist aber jetzt nicht mehr nötigt, so das ich den schlanker, von Wikipedia stammen Quellcode benutzen kann.
Der ist ebenfalls nicht korrekt.
Es kostet wirklich kaum Arbeit, den Code standardkonform und damit portabel zu machen, warum sträubst Du Dich mit Händen und Füßen dagegen?
Vor allem bewgst Du Dich auf kryptographischem Boden, da ist mehr als nur bloße Vorsicht geboten!
Naja bei JavaScript lag es nur daran, dass ein Integer Variable mehr als 32 Bit (auf dem gleichen Prozessor) speichern kann.
Das kann C auch. Sämtliche Größenangaben sind _nur_ Mindestangaben.
Wenn man aber nur die letzten 32 Bit betrachtet, läuft der Script so wie der C-Programm.
Nur, wenn Du auch bei C nur die letzten 32 Bit betrachtest und dafür sorgst, das die Variablen auch mindestens 32 Bit halten können.
Manchmal sollte man sich die Ausgabe doch Hexadezimal anstatt Integer sein, würde viel Zeit ersparen ^^.
Manchmal sollte man gleich standardkonform arbeiten, würde viel Zeit sparen.
Hättest Du den C-Code standardkonform geschrieben und danach in Javascript übersetzt hätte es erst gar keinen Fehler gegeben. Ist der C-Code immer noch nicht standardkonform paßt er jetzt übrigens nicht mehr zur Javascriptimplementation.
Und weil ich nicht so bin, gibt's hier eine standardkonforme C-Implementation. (die mögliche 64 Bit Implementation erspare ich Dir mal, Du sollst das ja auch nachvollziehen können.)
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/*
Das Macro _LITTLE_ENDIAN_ ist zur Bauzeit zu setzen.
Entweder händisch oder per [link:http://autoconf-archive.cryp.to/ac_c_bigendian_cross.html@title=Autoconfmacro]
*/
#ifdef _LITTLE_ENDIAN_
#ifndef XTEA_FAILURE
#define XTEA_FAILURE 0
#endif
#ifndef XTEA_SUCCESS
#define XTEA_SUCCESS 1
#endif
int encrypt(uint_least32_t *v, uint_least32_t *k);
int decrypt(uint_least32_t *v, uint_least32_t *k);
int encrypt(uint_least32_t *v, uint_least32_t *k){
uint_least32_t v0 = 0, v1 = 0;
uint_least32_t sum = 0, delta = 0x9E3779B9;
if(NULL == v || NULL == k) return XTEA_FAILURE;
v0 = v[0] & 0xFFFFFFFF;
v1 = v[1] & 0xFFFFFFFF;
for(int i=0; i<32; i++){
v0 += ( ((v1<<4 ^ v1>>5) +v1)
^ (sum + k[sum & 3])
) & 0xFFFFFFFF;
sum = (sum + delta) & 0xFFFFFFFF;
v1 += ( ((v0<<4 ^ v0>>5) +v0)
^ (sum + k[sum>>11 & 3])
) & 0xFFFFFFFF;
}
v[0] = v0;
v[1] = v1;
return XTEA_SUCCESS;
}
int decrypt(uint_least32_t *v, uint_least32_t *k){
uint_least32_t v0 = 0, v1 = 0;
uint_least32_t sum = 0xC6EF3720, delta = 0x9E3779B9;
if(NULL == v || NULL == k) return XTEA_FAILURE;
v0 = v[0] & 0xFFFFFFFF;
v1 = v[1] & 0xFFFFFFFF;
for(int i=0; i<32; i++){
v1 -= ( ((v0<<4 ^ v0>>5) +v0)
^ (sum + k[sum>>11 & 3])
) & 0xFFFFFFFF;
sum = (sum - delta) & 0xFFFFFFFF;
v0 -= ( ((v1<<4 ^ v1>>5) +v1)
^ (sum + k[sum & 3])
) & 0xFFFFFFFF;
}
v[0] = v0;
v[1] = v1;
return XTEA_SUCCESS;
}
#endif
#ifdef _XTEA_TEST_
int main(){
uint_least32_t v[2] = {0x41424344,0x45464748};
uint_least32_t k[4] = {0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f};
if(encrypt(v,k) == XTEA_FAILURE)
exit(EXIT_FAILURE);
printf("4142434445464748\n%8.8X%8.8X\n",v[0],v[1]);
if(decrypt(v,k) == XTEA_FAILURE)
exit(EXIT_FAILURE);
printf("497DF3D072612CB5\n%8.8X%8.8X\n",v[0],v[1]);
exit(EXIT_SUCCESS);
}
#endif
Ich hoffe mich nirgendwo vertippelt zu haben, ich hatte keine Lust die Sparcstation anzuschmeißen.
so short
Christoph Zurnieden