simple-mtpfs/src/simple-mtpfs-sha1.cpp

227 lines
6.4 KiB
C++

/* ***** BEGIN LICENSE BLOCK *****
* Copyright (C) 2012, Peter Hatina <phatina@gmail.com>
*
* 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; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ***** END LICENSE BLOCK ***** */
#include <config.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include "simple-mtpfs-sha1.h"
SHA1::SHA1()
{
reset();
}
void SHA1::update(const std::string &s)
{
std::istringstream is(s);
update(is);
}
void SHA1::update(std::istream &is)
{
std::string rest_of_buffer;
read(is, rest_of_buffer, BLOCK_BYTES - m_buffer.size());
m_buffer += rest_of_buffer;
while (is) {
uint32 block[BLOCK_INTS];
buffer_to_block(m_buffer, block);
transform(block);
read(is, m_buffer, BLOCK_BYTES);
}
}
std::string SHA1::final()
{
uint64 total_bits = (m_transforms * BLOCK_BYTES + m_buffer.size()) * 8;
m_buffer += static_cast<char>(0x80);
unsigned int orig_size = m_buffer.size();
while (m_buffer.size() < BLOCK_BYTES)
m_buffer += static_cast<char>(0x00);
uint32 block[BLOCK_INTS];
buffer_to_block(m_buffer, block);
if (orig_size > BLOCK_BYTES - 8) {
transform(block);
for (unsigned int i = 0; i < BLOCK_INTS - 2; ++i)
block[i] = 0;
}
block[BLOCK_INTS - 1] = total_bits;
block[BLOCK_INTS - 2] = (total_bits >> 32);
transform(block);
std::ostringstream result;
for (unsigned int i = 0; i < DIGEST_INTS; ++i) {
result << std::hex << std::setfill('0') << std::setw(8);
result << (m_digest[i] & 0xffffffff);
}
reset();
return result.str();
}
void SHA1::reset()
{
m_digest[0] = 0x67452301;
m_digest[1] = 0xefcdab89;
m_digest[2] = 0x98badcfe;
m_digest[3] = 0x10325476;
m_digest[4] = 0xc3d2e1f0;
m_transforms = 0;
m_buffer = "";
}
void SHA1::transform(uint32 block[BLOCK_BYTES])
{
uint32 a = m_digest[0];
uint32 b = m_digest[1];
uint32 c = m_digest[2];
uint32 d = m_digest[3];
uint32 e = m_digest[4];
#define rol(value, bits) (((value) << (bits)) | (((value) & 0xffffffff) >> (32 - (bits))))
#define blk(i) (block[i & 15] = rol(block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i & 15], 1))
#define R0(v,w,x,y,z,i) z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + rol(v,5); w = rol(w, 30);
#define R1(v,w,x,y,z,i) z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5a827999 + rol(v,5); w = rol(w, 30);
#define R2(v,w,x,y,z,i) z += (w ^ x ^ y) + blk(i) + 0x6ed9eba1 + rol(v,5); w = rol(w, 30);
#define R3(v,w,x,y,z,i) z += (((w | x) & y) | ( w & x)) + blk(i) + 0x8f1bbcdc + rol(v,5); w = rol(w, 30);
#define R4(v,w,x,y,z,i) z += (w ^ x ^ y) + blk(i) + 0xca62c1d6 + rol(v,5); w = rol(w, 30);
R0(a, b, c, d, e, 0);
R0(e, a, b, c, d, 1);
R0(d, e, a, b, c, 2);
R0(c, d, e, a, b, 3);
R0(b, c, d, e, a, 4);
R0(a, b, c, d, e, 5);
R0(e, a, b, c, d, 6);
R0(d, e, a, b, c, 7);
R0(c, d, e, a, b, 8);
R0(b, c, d, e, a, 9);
R0(a, b, c, d, e, 10);
R0(e, a, b, c, d, 11);
R0(d, e, a, b, c, 12);
R0(c, d, e, a, b, 13);
R0(b, c, d, e, a, 14);
R0(a, b, c, d, e, 15);
R1(e, a, b, c, d, 16);
R1(d, e, a, b, c, 17);
R1(c, d, e, a, b, 18);
R1(b, c, d, e, a, 19);
R2(a, b, c, d, e, 20);
R2(e, a, b, c, d, 21);
R2(d, e, a, b, c, 22);
R2(c, d, e, a, b, 23);
R2(b, c, d, e, a, 24);
R2(a, b, c, d, e, 25);
R2(e, a, b, c, d, 26);
R2(d, e, a, b, c, 27);
R2(c, d, e, a, b, 28);
R2(b, c, d, e, a, 29);
R2(a, b, c, d, e, 30);
R2(e, a, b, c, d, 31);
R2(d, e, a, b, c, 32);
R2(c, d, e, a, b, 33);
R2(b, c, d, e, a, 34);
R2(a, b, c, d, e, 35);
R2(e, a, b, c, d, 36);
R2(d, e, a, b, c, 37);
R2(c, d, e, a, b, 38);
R2(b, c, d, e, a, 39);
R3(a, b, c, d, e, 40);
R3(e, a, b, c, d, 41);
R3(d, e, a, b, c, 42);
R3(c, d, e, a, b, 43);
R3(b, c, d, e, a, 44);
R3(a, b, c, d, e, 45);
R3(e, a, b, c, d, 46);
R3(d, e, a, b, c, 47);
R3(c, d, e, a, b, 48);
R3(b, c, d, e, a, 49);
R3(a, b, c, d, e, 50);
R3(e, a, b, c, d, 51);
R3(d, e, a, b, c, 52);
R3(c, d, e, a, b, 53);
R3(b, c, d, e, a, 54);
R3(a, b, c, d, e, 55);
R3(e, a, b, c, d, 56);
R3(d, e, a, b, c, 57);
R3(c, d, e, a, b, 58);
R3(b, c, d, e, a, 59);
R4(a, b, c, d, e, 60);
R4(e, a, b, c, d, 61);
R4(d, e, a, b, c, 62);
R4(c, d, e, a, b, 63);
R4(b, c, d, e, a, 64);
R4(a, b, c, d, e, 65);
R4(e, a, b, c, d, 66);
R4(d, e, a, b, c, 67);
R4(c, d, e, a, b, 68);
R4(b, c, d, e, a, 69);
R4(a, b, c, d, e, 70);
R4(e, a, b, c, d, 71);
R4(d, e, a, b, c, 72);
R4(c, d, e, a, b, 73);
R4(b, c, d, e, a, 74);
R4(a, b, c, d, e, 75);
R4(e, a, b, c, d, 76);
R4(d, e, a, b, c, 77);
R4(c, d, e, a, b, 78);
R4(b, c, d, e, a, 79);
m_digest[0] += a;
m_digest[1] += b;
m_digest[2] += c;
m_digest[3] += d;
m_digest[4] += e;
m_transforms++;
}
void SHA1::buffer_to_block(const std::string &buffer, uint32 block[BLOCK_BYTES])
{
for (unsigned int i = 0; i < BLOCK_INTS; ++i) {
block[i] = (buffer[4 * i + 3] & 0xff)
| (buffer[4 * i + 2] & 0xff) << 8
| (buffer[4 * i + 1] & 0xff) << 16
| (buffer[4 * i + 0] & 0xff) << 24;
}
}
void SHA1::read(std::istream &is, std::string &s, const int max)
{
char sbuf[BLOCK_BYTES];
is.read(sbuf, max);
s.assign(sbuf, is.gcount());
}
std::string SHA1::sumString(const std::string &str)
{
SHA1 sha1;
sha1.update(str);
return sha1.final();
}