sha1.cpp

Go to the documentation of this file.
00001 /* $Id: sha1.cpp 52830 2012-01-31 00:36:56Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2007 - 2012 by Benoit Timbert <benoit.timbert@free.fr>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  *  @file
00018  *  Secure Hash Algorithm 1 (SHA-1).
00019  *  Used to checksum the game-config / cache.
00020  */
00021 
00022 /* This is supposed to be an implementation of the
00023    Secure Hash Algorithm 1 (SHA-1)
00024 
00025    Check RFC 3174 for details about the algorithm.
00026 
00027    Currently this implementation might produce different results on little-
00028    and big-endian machines, but for our current usage, we don't care :)
00029 */
00030 
00031 #include "sha1.hpp"
00032 
00033 #include <iomanip>
00034 #include <sstream>
00035 
00036 #define sha_rotl(n,x)       ( ((x) << (n)) | ((x) >> (32-(n))) )
00037 #define sha_ch(x,y,z)       ( ((x) & (y)) | ((~(x)) & (z)) )
00038 #define sha_parity(x,y,z)   ( (x) ^ (y) ^ (z) )
00039 #define sha_maj(x,y,z)      ( ((x) & (y)) | ((x) & (z)) | ((y) & (z)) )
00040 
00041 std::string sha1_hash::display() {
00042     std::stringstream s;
00043     s << std::hex << std::setfill('0') << std::setw(8) << H0;
00044     s << std::hex << std::setfill('0') << std::setw(8) << H1;
00045     s << std::hex << std::setfill('0') << std::setw(8) << H2;
00046     s << std::hex << std::setfill('0') << std::setw(8) << H3;
00047     s << std::hex << std::setfill('0') << std::setw(8) << H4;
00048     return s.str();
00049 }
00050 
00051 sha1_hash::sha1_hash(const std::string& str)
00052 : H0(0x67452301), H1(0xefcdab89), H2(0x98badcfe), H3(0x10325476), H4(0xc3d2e1f0)
00053 {
00054     Uint8 block[64];
00055 
00056     int bytes_left = str.size();
00057     Uint32 ssz = bytes_left * 8; // string length in bits
00058 
00059     std::stringstream iss (str, std::stringstream::in);
00060     // cut our string in 64 bytes blocks then process it
00061     while (bytes_left > 0) {
00062         iss.read(reinterpret_cast<char*>(block), 64);
00063         if (bytes_left <= 64) { // if it's the last block, pad it
00064             if (bytes_left < 64) {
00065                 block[bytes_left]= 0x80; // add a 1 bit right after the end of the string
00066             }
00067             int i;
00068             for (i = 63; i > bytes_left; i--) {
00069                 block[i]=0; // pad our block with zeros
00070             }
00071             if (bytes_left < 56) { // enough space to store the length
00072                 // put the length at the end of the block
00073                 block[60] = ssz >> 24;
00074 #ifdef _MSC_VER
00075 #pragma warning (push)
00076 #pragma warning (disable: 4244)
00077 #endif
00078                 block[61] = ssz >> 16;
00079                 block[62] = ssz >> 8;
00080                 block[63] = ssz;
00081 #ifdef _MSC_VER
00082 #pragma warning (pop)
00083 #endif
00084             } else { // not enough space for the zeros => we need a new block
00085                 next(block);
00086                 // new block
00087                 for (i = 0; i < 60 ; i++) {
00088                     block[i]=0; // pad our block with zeros
00089                 }
00090                 if (bytes_left == 64) {
00091                     block[0]= 0x80; // add a 1 bit right after the end of the string = beginning of our new block
00092                 }
00093                 // put the length at the end of the block
00094                 block[60] = ssz >> 24;
00095 #ifdef _MSC_VER
00096 #pragma warning (push)
00097 #pragma warning (disable: 4244)
00098 #endif
00099                 block[61] = ssz >> 16;
00100                 block[62] = ssz >> 8;
00101                 block[63] = ssz;
00102 #ifdef _MSC_VER
00103 #pragma warning (pop)
00104 #endif
00105             }
00106         }
00107         next(block);
00108         bytes_left -= 64;
00109     }
00110 }
00111 
00112 void sha1_hash::next(Uint8 block[64]) {
00113     Uint32 W[80];
00114     Uint32 A, B, C, D, E, T;
00115     int i;
00116 
00117     A = H0;
00118     B = H1;
00119     C = H2;
00120     D = H3;
00121     E = H4;
00122     for (i = 0; i < 16; i++) {
00123         W[i]= (block[4 * i] << 24) | (block[4 * i + 1] << 16) | (block[4 * i + 2] << 8) | block[4 * i + 3];
00124     }
00125     for (; i < 80; i++) {
00126         W[i]=sha_rotl(1, W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]);
00127     }
00128     for (i = 0; i < 20; i++) {
00129         T = sha_rotl(5,A) + sha_ch(B,C,D) + E + W[i] + 0x5a827999;
00130         E = D;
00131         D = C;
00132         C = sha_rotl(30,B);
00133         B = A;
00134         A = T;
00135     }
00136     for (; i < 40; i++) {
00137         T = sha_rotl(5,A) + sha_parity(B,C,D) + E + W[i] + 0x6ed9eba1;
00138         E = D;
00139         D = C;
00140         C = sha_rotl(30,B);
00141         B = A;
00142         A = T;
00143     }
00144     for (; i < 60; i++) {
00145         T = sha_rotl(5,A) + sha_maj(B,C,D) + E + W[i] + 0x8f1bbcdc;
00146         E = D;
00147         D = C;
00148         C = sha_rotl(30,B);
00149         B = A;
00150         A = T;
00151     }
00152     for (; i < 80; i++) {
00153         T = sha_rotl(5,A) + sha_parity(B,C,D) + E + W[i] + 0xca62c1d6;
00154         E = D;
00155         D = C;
00156         C = sha_rotl(30,B);
00157         B = A;
00158         A = T;
00159     }
00160     H0 += A;
00161     H1 += B;
00162     H2 += C;
00163     H3 += D;
00164     H4 += E;
00165 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:10 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs