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