Bonjour,

J'ai un bout de code tout simple qui est censé renvoyer la somme SHA-1 d'une chaîne de caractères. Mais voilà, le résultat n'est pas ce qu'il devrait être.

Exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
./main
abc::7677e034471f55306438b4e5bd230fe65f4f31e9
Alors que c'est censé être a9993e364706816aba3e25717850c26c9cd0d89d.

Voici le code de main.cpp :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <string>
#include "sha1.hpp"
using namespace std;
 
int main(int argc, char *argv[]) {
	sha1_hash resultat("abc"); // a9993e364706816aba3e25717850c26c9cd0d89d
	cout << "abc::" << resultat.display() << endl;
	return 0;
}
sha1.hpp :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* $Id: sha1.hpp 46186 2010-09-01 21:12:38Z silene $ */
/*
   Copyright (C) 2007 - 2010 by Benoit Timbert <benoit.timbert@free.fr>
   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.
 
   See the COPYING file for more details.
*/
 
#ifndef SHA1_H_INCLUDED
#define SHA1_H_INCLUDED
 
#include <string>
#include <SDL/SDL_stdinc.h>
 
class sha1_hash
{
public:
 
	/** Make a hash from a string */
	sha1_hash(const std::string& str);
 
	/** Display the hash */
	std::string display();
private:
 
	/** Process the next 512 bits block */
	void next(Uint8 block[64]);
	Uint32 H0, H1, H2, H3, H4;
 
};
 
#endif
sha1.cpp :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* $Id: sha1.cpp 46186 2010-09-01 21:12:38Z silene $ */
/*
   Copyright (C) 2007 - 2010 by Benoit Timbert <benoit.timbert@free.fr>
   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.
 
   See the COPYING file for more details.
*/
 
/**
 *  @file
 *  Secure Hash Algorithm 1 (SHA-1).
 *  Used to checksum the game-config / cache.
 */
 
/* This is supposed to be an implementation of the
   Secure Hash Algorithm 1 (SHA-1)
 
   Check RFC 3174 for details about the algorithm.
 
   Currently this implementation might produce different results on little-
   and big-endian machines, but for our current usage, we don't care :)
*/
 
#include "sha1.hpp"
 
#include <iomanip>
#include <sstream>
 
#define sha_rotl(n,x)		( ((x) << (n)) | ((x) >> (32-(n))) )
#define sha_ch(x,y,z)		( ((x) & (y)) | ((!(x)) & (z)) )
#define sha_parity(x,y,z)	( (x) ^ (y) ^ (z) )
#define sha_maj(x,y,z)		( ((x) & (y)) | ((x) & (z)) | ((y) & (z)) )
 
std::string sha1_hash::display() {
	std::stringstream s;
	s << std::hex << std::setfill('0') << std::setw(8) << H0;
	s << std::hex << std::setfill('0') << std::setw(8) << H1;
	s << std::hex << std::setfill('0') << std::setw(8) << H2;
	s << std::hex << std::setfill('0') << std::setw(8) << H3;
	s << std::hex << std::setfill('0') << std::setw(8) << H4;
	return s.str();
}
 
sha1_hash::sha1_hash(const std::string& str)
: H0(0x67452301), H1(0xefcdab89), H2(0x98badcfe), H3(0x10325476), H4(0xc3d2e1f0)
{
	Uint8 block[64];
 
	int bytes_left = str.size();
	Uint32 ssz = bytes_left * 8; // string length in bits
 
	std::stringstream iss (str, std::stringstream::in);
	// cut our string in 64 bytes blocks then process it
	while (bytes_left > 0) {
		iss.read(reinterpret_cast<char*>(block), 64);
		if (bytes_left <= 64) { // if it's the last block, pad it
			if (bytes_left < 64) {
				block[bytes_left]= 0x80; // add a 1 bit right after the end of the string
			}
			int i;
			for (i = 63; i > bytes_left; i--) {
				block[i]=0; // pad our block with zeros
			}
			if (bytes_left < 60) { // enough space to store the length
				// put the length at the end of the block
				block[60] = ssz >> 24;
				block[61] = ssz >> 16;
				block[62] = ssz >> 8;
				block[63] = ssz;
			} else { // not enough space for the zeros => we need a new block
				next(block);
				// new block
				for (i = 0; i < 60 ; i++) {
					block[i]=0; // pad our block with zeros
				}
				if (bytes_left == 64) {
					block[0]= 0x80; // add a 1 bit right after the end of the string = beginning of our new block
				}
				// put the length at the end of the block
				block[60] = ssz >> 24;
				block[61] = ssz >> 16;
				block[62] = ssz >> 8;
				block[63] = ssz;
			}
		}
		next(block);
		bytes_left -= 64;
	}
}
 
void sha1_hash::next(Uint8 block[64]) {
	Uint32 W[80];
	Uint32 A, B, C, D, E, T;
	int i;
 
	A = H0;
	B = H1;
	C = H2;
	D = H3;
	E = H4;
	for (i = 0; i < 16; i++) {
		W[i]= (block[4 * i] << 24) | (block[4 * i + 1] << 16) | (block[4 * i + 2] << 8) | block[4 * i + 3];
	}
	for (; i < 80; i++) {
		W[i]=sha_rotl(1, W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]);
	}
	for (i = 0; i < 20; i++) {
		T = sha_rotl(5,A) + sha_ch(B,C,D) + E + W[i] + 0x5a827999;
		E = D;
		D = C;
		C = sha_rotl(30,B);
		B = A;
		A = T;
	}
	for (; i < 40; i++) {
		T = sha_rotl(5,A) + sha_parity(B,C,D) + E + W[i] + 0x6ed9eba1;
		E = D;
		D = C;
		C = sha_rotl(30,B);
		B = A;
		A = T;
	}
	for (; i < 60; i++) {
		T = sha_rotl(5,A) + sha_maj(B,C,D) + E + W[i] + 0x8f1bbcdc;
		E = D;
		D = C;
		C = sha_rotl(30,B);
		B = A;
		A = T;
	}
	for (; i < 80; i++) {
		T = sha_rotl(5,A) + sha_parity(B,C,D) + E + W[i] + 0xca62c1d6;
		E = D;
		D = C;
		C = sha_rotl(30,B);
		B = A;
		A = T;
	}
	H0 += A;
	H1 += B;
	H2 += C;
	H3 += D;
	H4 += E;
}
Et les options de compilation :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
g++ -Wall -pedantic -O3 *.cpp -o main
Je suis sous Debian GNU/Linux Squeeze 64 bits.
La bibliothèque vient du jeu libre Battle for Wesnoth.

Avez-vous une idée d'où je me serais trompé ?
Merci d'avance