| 12
 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;
} | 
Partager