Exheredludis/paludis/util/rmd160.cc
Saleem Abdulrasool f3cd245511 modernize: convert to range based for-loops
Automated conversion to range based for loops.  NFC
2016-08-04 22:11:01 -07:00

238 lines
6.3 KiB
C++

/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2006 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* Paludis 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, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "rmd160.hh"
#include <paludis/util/attributes.hh>
#include <paludis/util/digest_registry.hh>
#include <sstream>
#include <istream>
#include <iomanip>
using namespace paludis;
/*
* Implemented based upon the description at:
* http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
*/
namespace
{
inline uint32_t rl(uint32_t x, unsigned int shift) PALUDIS_ATTRIBUTE((always_inline));
inline uint32_t rl(uint32_t x, unsigned int shift)
{
return (x << shift) | (x >> (32 - shift));
}
inline uint32_t _f(uint32_t j, uint32_t x, uint32_t y, uint32_t z) PALUDIS_ATTRIBUTE((always_inline));
inline uint32_t _f(uint32_t j, uint32_t x, uint32_t y, uint32_t z)
{
switch (j / 16)
{
case 0:
return x ^ y ^ z;
case 1:
return (x & y) | (~x & z);
case 2:
return (x | ~y) ^ z;
case 3:
return (x & z) | (y & ~z);
case 4:
return x ^ (y | ~z);
}
throw 0;
}
inline uint32_t _x(unsigned i, const uint8_t * const block) PALUDIS_ATTRIBUTE((always_inline));
inline uint32_t _x(unsigned i, const uint8_t * const block)
{
return
(block[(i << 2) + 3] << 24) |
(block[(i << 2) + 2] << 16) |
(block[(i << 2) + 1] << 8) |
(block[(i << 2) + 0]);
}
inline uint32_t _e(const uint32_t x) PALUDIS_ATTRIBUTE((always_inline));
inline uint32_t _e(const uint32_t x)
{
return
((x & 0xff) << 24) |
((x & 0xff00) << 8) |
((x & 0xff0000) >> 8) |
((x & 0xff000000) >> 24);
}
}
void
RMD160::_update(const uint8_t * const block)
{
uint32_t a(_h[0]), b(_h[1]), c(_h[2]), d(_h[3]), e(_h[4]);
uint32_t ap(_h[0]), bp(_h[1]), cp(_h[2]), dp(_h[3]), ep(_h[4]);
uint32_t t;
for (unsigned j(0) ; j <= 79 ; ++j)
{
t = a + _f(j, b, c, d) + _x(_r[j], block) + _k[j / 16];
t = rl(t, _s[j]) + e;
a = e;
e = d;
d = rl(c, 10);
c = b;
b = t;
t = ap + _f(79 - j, bp, cp, dp) + _x(_rp[j], block) + _kp[j / 16];
t = rl(t, _sp[j]) + ep;
ap = ep;
ep = dp;
dp = rl(cp, 10);
cp = bp;
bp = t;
}
t = _h[1] + c + dp;
_h[1] = _h[2] + d + ep;
_h[2] = _h[3] + e + ap;
_h[3] = _h[4] + a + bp;
_h[4] = _h[0] + b + cp;
_h[0] = t;
}
RMD160::RMD160(std::istream & stream) :
_size(0),
_done_one_pad(false)
{
_h[0] = 0x67452301;
_h[1] = 0xefcdab89;
_h[2] = 0x98badcfe;
_h[3] = 0x10325476;
_h[4] = 0xc3d2e1f0;
uint8_t buffer[64];
int c, s(0);
while (-1 != ((c = _get(stream))))
{
buffer[s++] = c;
if (64 == s)
{
_update(&buffer[0]);
s = 0;
}
}
while (56 != s)
{
buffer[s++] = 0;
if (64 == s)
{
_update(&buffer[0]);
s = 0;
}
}
buffer[56] = static_cast<uint8_t>(_size >> (0 * 8));
buffer[57] = static_cast<uint8_t>(_size >> (1 * 8));
buffer[58] = static_cast<uint8_t>(_size >> (2 * 8));
buffer[59] = static_cast<uint8_t>(_size >> (3 * 8));
buffer[60] = static_cast<uint8_t>(_size >> (4 * 8));
buffer[61] = static_cast<uint8_t>(_size >> (5 * 8));
buffer[62] = static_cast<uint8_t>(_size >> (6 * 8));
buffer[63] = static_cast<uint8_t>(_size >> (7 * 8));
_update(&buffer[0]);
}
std::string
RMD160::hexsum() const
{
std::stringstream result;
for (unsigned int j : _h)
result << std::hex << std::right << std::setw(8) << std::setfill('0') <<
_e(static_cast<unsigned int>(j)) << std::flush;
return result.str();
}
int
RMD160::_get(std::istream & stream)
{
char c;
if (stream.get(c))
{
_size += 8;
return static_cast<unsigned char>(c);
}
else if (! _done_one_pad)
{
_done_one_pad = true;
return 0x80;
}
else
return -1;
}
const uint8_t RMD160::_r[80] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
};
const uint8_t RMD160::_rp[80] = {
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
};
const uint8_t RMD160::_s[80] = {
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
};
const uint8_t RMD160::_sp[80] = {
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
};
const uint32_t RMD160::_k[5] = {
0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e
};
const uint32_t RMD160::_kp[5] = {
0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000
};
namespace
{
DigestRegistry::Registration<RMD160> registration("RMD160");
}