C++ : SHA1-Fehler

Ich habe ein kleines Problem mit einer SHA-1 Umsetzung unter C++ bzw. C. Der unten aufgeführte Code funktioniert zwar Prima, doch bei dem hashen von z.B. "ü" kommt es zu einem Hash, der lediglich 39 Zeichen enthält. Könnt ihr mir sagen wo der Fehler liegt bzw. eine korregierte Version vorlegen? Danke!
Code:
	string SHA1(unsigned char* str1)
	{
		#define rotateleft(x,n) ((x<<n) | (x>>(32-n)))
		#define rotateright(x,n) ((x>>n) | (x<<(32-n)))
		unsigned long int h0,h1,h2,h3,h4,a,b,c,d,e,f,k,i,j,temp;

		h0 = 0x67452301;
		h1 = 0xEFCDAB89;
		h2 = 0x98BADCFE;
		h3 = 0x10325476;
		h4 = 0xC3D2E1F0;

		unsigned char* str;
		str = (unsigned char*)malloc(strlen((const char*)str1)+100);
		strcpy((char*)str,(const char*)str1);
		//str = str1;
	
		int current_length = strlen((const char*)str);
		int original_length = current_length;
		str[current_length] = 0x80;
		str[current_length + 1] = '\0';	

		char ic = str[current_length];
		current_length++;

		int ib = current_length % 64;
		if(ib<56)
			ib = 56-ib;
		else
			ib = 120 - ib;

		for(i=0;i < ib;i++)
		{
			str[current_length]=0x00;
			current_length++;
		}
		str[current_length + 1]='\0';

		for(i=0;i<6;i++)
		{
			str[current_length]=0x0;
			current_length++;
		}
		str[current_length] = (original_length * 8) / 0x100 ;
		current_length++;
		str[current_length] = (original_length * 8) % 0x100;
		current_length++;
		str[current_length+i]='\0';

		int number_of_chunks = current_length/64;
		unsigned long int word[80];
		for(i=0;i<number_of_chunks;i++)
		{
			for(j=0;j<16;j++)
			{
				word[j] = str[i*64 + j*4 + 0] * 0x1000000 + str[i*64 + j*4 + 1] * 0x10000 + str[i*64 + j*4 + 2] * 0x100 + str[i*64 + j*4 + 3];
			}
			for(j=16;j<80;j++)
			{
				word[j] = rotateleft((word[j-3] ^ word[j-8] ^ word[j-14] ^ word[j-16]),1);
			}

			a = h0;
			b = h1;
			c = h2;
			d = h3;
			e = h4;

			for(int m=0;m<80;m++)
			{
				if(m<=19)
				{
					f = (b & c) | ((~b) & d);
					k = 0x5A827999;
				}
				else if(m<=39)
				{
					f = b ^ c ^ d;
					k = 0x6ED9EBA1;
				}
				else if(m<=59)
				{
					f = (b & c) | (b & d) | (c & d);
					k = 0x8F1BBCDC;
				}
				else
				{
					f = b ^ c ^ d;
					k = 0xCA62C1D6; 
				}

				temp = (rotateleft(a,5) + f + e + k + word[m]) & 0xFFFFFFFF;
				e = d;
				d = c;
				c = rotateleft(b,30);
				b = a;
				a = temp;
			}
			h0 = h0 + a;
			h1 = h1 + b;
			h2 = h2 + c;
			h3 = h3 + d;
			h4 = h4 + e;
		}
		stringstream ss;
		ss << hex << h0 << h1 << h2 << h3 << h4;
		cout << ss.str() << endl;
		cout << ss.str().length() << endl;
		return ss.str();
	}

PS:
So wird das ganze übergeben:
Code:
	string Password;
	getline(cin, Password);
	char* PW_char = const_cast<char*>(Password.c_str());
	string SHA_1 = Encrypt.SHA1((unsigned char *)PW_char);
 
Hallo,
1. Bitte ein Beispiel geben: String + den Hashwert
2. Liegt es evt. dran, dass ein Wort die Form 0ABCDEF... hat, also eine führende 0, und diese bei der Konvertierung in den String weggelassen wird?
3. Debugger benutzen. Geh per Debugger dein Programm durch und schau was am ende der Berechnung in den Variablen h0,...,h4 steht
 
String: "ü"
Hash dazu: "a3f294235fe542205ae9bc3a0d1bffe12cf235" (nur 39 Zeichen)
Eig. Hash (laut fileformat.info): "94a759fd37735430753c7b6b80684306d80ea16e" (40)

h0 bis h4 sind nur die Unterteilungen, also jeweils 10 Zeichen von dem Hash.
Sämtliche andere Hashes sind korrekt, auch von "ä". "ö" funktioniert wiederrum nicht...

EDIT:
Ich vermute, es hängt damit zusammen, dass bei einer Umwandlung von Char zu Int bzw. Dezimal die Sonderzeichen negativ dargestellt werden. Bei "ü" und "ö" wäre das im 2-stelligen negativen Bereich, bei "ä" lediglich im 1-stelligen. Sonst sehe ich keinen Grund, wieso es nur bei "ä" funktioniert.
 
Dann hat deine Implementierung anscheinend 2 Probleme, denn Elderans Hinweis trifft auch zu: Wäre h1 z.b. "01234567", so würde es bei der Formatierung( ss << hex << ..) zu "1234567" und damit fiele ein Zeichen weg.
 
Danke für die Antworten, ich konnte das Problem nun lösen!
Nun habe ich aber noch eine weitere Frage, die sich auf die Optimierung eines Ablaufes bezieht. Ich habe 2 Schleifen und jede läuft als Bsp. ca. 500.000 Mal (auch noch häufiger) durch. In diesen Schleifen soll jedes mal ein wert in einem Array oder etwas ähnlichem (stringstream, vector, sprintf, usw...) abgespeichert werden. Dies muss so schnell wie möglich passieren.
Welche Funktion sollte ich hierbei verwenden?
 
Vielleicht verstehe ich dich falsch, aber ich meine nicht die Funktion mit der ich auf das Array oder ähnliches zugreife (.at() bzw. []), sondern den eig. Container.
Zum Beispiel kann ich einfach an einen String immerwieder etwas konkatenieren. Dies war bei mir bisher die schnellste Methodik. Am besten wäre es, wenn es in Assembler gehen würde, da die Geschwindigkeit dort noch einmal erhöht werden könnte...

MfG Switch.
 
csde_rats meinte anstatt der STL-Container wie vector, stringstream, etc. ein normales Array zu verwenden. Das ist dann auch, bei einem vernünftigen Compiler, mindestens genauso schnell wie es per Hand in Assembly zu schreiben. (Ich schreibe mindestens, da Compiler oft besser bzgl. Pipelining etc. optimieren können)
 
Zurück
Oben