Add RIPEMD160 implementation
This commit is contained in:
parent
03a95ac05b
commit
b33cb706c8
@ -51,6 +51,8 @@ UTIL_FILES = \
|
|||||||
hash/pbkdf1.hpp \
|
hash/pbkdf1.hpp \
|
||||||
hash/pbkdf2.cpp \
|
hash/pbkdf2.cpp \
|
||||||
hash/pbkdf2.hpp \
|
hash/pbkdf2.hpp \
|
||||||
|
hash/ripemd.cpp \
|
||||||
|
hash/ripemd.hpp \
|
||||||
hash/sha1.cpp \
|
hash/sha1.cpp \
|
||||||
hash/sha1.hpp \
|
hash/sha1.hpp \
|
||||||
image.cpp \
|
image.cpp \
|
||||||
|
367
hash/ripemd.cpp
Normal file
367
hash/ripemd.cpp
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of libgim
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* Copyright 2014 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ripemd.hpp"
|
||||||
|
|
||||||
|
#include "debug.hpp"
|
||||||
|
#include "bitwise.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
|
using util::hash::RIPEMD;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
RIPEMD::RIPEMD()
|
||||||
|
{
|
||||||
|
reset ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
RIPEMD::reset (void) {
|
||||||
|
m_state[0] = 0x67452301u;
|
||||||
|
m_state[1] = 0xEFCDAB89u;
|
||||||
|
m_state[2] = 0x98BADCFEu;
|
||||||
|
m_state[3] = 0x10325476u;
|
||||||
|
m_state[4] = 0xC3D2E1F0u;
|
||||||
|
|
||||||
|
m_length = 0;
|
||||||
|
|
||||||
|
m_buffer.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
RIPEMD::update(const uint8_t *data, size_t len) {
|
||||||
|
CHECK_HARD (data);
|
||||||
|
|
||||||
|
size_t cursor = 0;
|
||||||
|
|
||||||
|
while (cursor < len) {
|
||||||
|
size_t width = sizeof (m_buffer.d08) - m_buffer.size;
|
||||||
|
size_t chunk = min (width, len - cursor);
|
||||||
|
|
||||||
|
memcpy (m_buffer.d08 + m_buffer.size, data + cursor, chunk);
|
||||||
|
m_length += chunk;
|
||||||
|
m_buffer.size += chunk;
|
||||||
|
|
||||||
|
if (m_buffer.size == sizeof (m_buffer.d08))
|
||||||
|
transform ();
|
||||||
|
|
||||||
|
cursor += chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_length >> sizeof (m_length) * 8 - 3 != 0)
|
||||||
|
throw std::length_error ("exceeded maximum message length");
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
static constexpr
|
||||||
|
uint32_t
|
||||||
|
f1 (uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; }
|
||||||
|
|
||||||
|
static constexpr
|
||||||
|
uint32_t
|
||||||
|
f2 (uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); }
|
||||||
|
|
||||||
|
static constexpr
|
||||||
|
uint32_t
|
||||||
|
f3 (uint32_t x, uint32_t y, uint32_t z) { return (x | ~y) ^ z; }
|
||||||
|
|
||||||
|
static constexpr
|
||||||
|
uint32_t
|
||||||
|
f4 (uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); }
|
||||||
|
|
||||||
|
static constexpr
|
||||||
|
uint32_t
|
||||||
|
f5 (uint32_t x, uint32_t y, uint32_t z) { return x ^ (y | ~z); }
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
RIPEMD::transform (void) {
|
||||||
|
CHECK_EQ (m_buffer.size, sizeof (m_buffer.d32));
|
||||||
|
|
||||||
|
// Use: boolean function f
|
||||||
|
// state parameters a, b, c, d, e
|
||||||
|
// offset value o
|
||||||
|
// input data value x
|
||||||
|
// shift length s
|
||||||
|
|
||||||
|
#define ROUND(f,a,b,c,d,e,o,x,s) { \
|
||||||
|
a += f(b, c, d); \
|
||||||
|
a += m_buffer.d32[x] + o; \
|
||||||
|
a = rotatel (a, s); \
|
||||||
|
a += e; \
|
||||||
|
c = rotatel (c, 10); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define R1a(a,b,c,d,e,x,s) ROUND(f1,a,b,c,d,e,0x00000000u,x,s)
|
||||||
|
#define R2a(a,b,c,d,e,x,s) ROUND(f2,a,b,c,d,e,0x5A827999u,x,s)
|
||||||
|
#define R3a(a,b,c,d,e,x,s) ROUND(f3,a,b,c,d,e,0x6ED9EBA1u,x,s)
|
||||||
|
#define R4a(a,b,c,d,e,x,s) ROUND(f4,a,b,c,d,e,0x8F1BBCDCu,x,s)
|
||||||
|
#define R5a(a,b,c,d,e,x,s) ROUND(f5,a,b,c,d,e,0xA953FD4Eu,x,s)
|
||||||
|
|
||||||
|
#define R1b(a,b,c,d,e,x,s) ROUND(f5,a,b,c,d,e,0x50A28BE6u,x,s)
|
||||||
|
#define R2b(a,b,c,d,e,x,s) ROUND(f4,a,b,c,d,e,0x5C4DD124u,x,s)
|
||||||
|
#define R3b(a,b,c,d,e,x,s) ROUND(f3,a,b,c,d,e,0x6D703EF3u,x,s)
|
||||||
|
#define R4b(a,b,c,d,e,x,s) ROUND(f2,a,b,c,d,e,0x7A6D76E9u,x,s)
|
||||||
|
#define R5b(a,b,c,d,e,x,s) ROUND(f1,a,b,c,d,e,0x00000000u,x,s)
|
||||||
|
|
||||||
|
uint32_t a1, b1, c1, d1, e1;
|
||||||
|
uint32_t a2, b2, c2, d2, e2;
|
||||||
|
|
||||||
|
a1 = a2 = m_state[0];
|
||||||
|
b1 = b2 = m_state[1];
|
||||||
|
c1 = c2 = m_state[2];
|
||||||
|
d1 = d2 = m_state[3];
|
||||||
|
e1 = e2 = m_state[4];
|
||||||
|
|
||||||
|
// Left round 1
|
||||||
|
R1a(a1, b1, c1, d1, e1, 0, 11);
|
||||||
|
R1a(e1, a1, b1, c1, d1, 1, 14);
|
||||||
|
R1a(d1, e1, a1, b1, c1, 2, 15);
|
||||||
|
R1a(c1, d1, e1, a1, b1, 3, 12);
|
||||||
|
R1a(b1, c1, d1, e1, a1, 4, 5);
|
||||||
|
R1a(a1, b1, c1, d1, e1, 5, 8);
|
||||||
|
R1a(e1, a1, b1, c1, d1, 6, 7);
|
||||||
|
R1a(d1, e1, a1, b1, c1, 7, 9);
|
||||||
|
R1a(c1, d1, e1, a1, b1, 8, 11);
|
||||||
|
R1a(b1, c1, d1, e1, a1, 9, 13);
|
||||||
|
R1a(a1, b1, c1, d1, e1, 10, 14);
|
||||||
|
R1a(e1, a1, b1, c1, d1, 11, 15);
|
||||||
|
R1a(d1, e1, a1, b1, c1, 12, 6);
|
||||||
|
R1a(c1, d1, e1, a1, b1, 13, 7);
|
||||||
|
R1a(b1, c1, d1, e1, a1, 14, 9);
|
||||||
|
R1a(a1, b1, c1, d1, e1, 15, 8);
|
||||||
|
|
||||||
|
// Left round 2
|
||||||
|
R2a(e1, a1, b1, c1, d1, 7, 7);
|
||||||
|
R2a(d1, e1, a1, b1, c1, 4, 6);
|
||||||
|
R2a(c1, d1, e1, a1, b1, 13, 8);
|
||||||
|
R2a(b1, c1, d1, e1, a1, 1, 13);
|
||||||
|
R2a(a1, b1, c1, d1, e1, 10, 11);
|
||||||
|
R2a(e1, a1, b1, c1, d1, 6, 9);
|
||||||
|
R2a(d1, e1, a1, b1, c1, 15, 7);
|
||||||
|
R2a(c1, d1, e1, a1, b1, 3, 15);
|
||||||
|
R2a(b1, c1, d1, e1, a1, 12, 7);
|
||||||
|
R2a(a1, b1, c1, d1, e1, 0, 12);
|
||||||
|
R2a(e1, a1, b1, c1, d1, 9, 15);
|
||||||
|
R2a(d1, e1, a1, b1, c1, 5, 9);
|
||||||
|
R2a(c1, d1, e1, a1, b1, 2, 11);
|
||||||
|
R2a(b1, c1, d1, e1, a1, 14, 7);
|
||||||
|
R2a(a1, b1, c1, d1, e1, 11, 13);
|
||||||
|
R2a(e1, a1, b1, c1, d1, 8, 12);
|
||||||
|
|
||||||
|
// Left round 3
|
||||||
|
R3a(d1, e1, a1, b1, c1, 3, 11);
|
||||||
|
R3a(c1, d1, e1, a1, b1, 10, 13);
|
||||||
|
R3a(b1, c1, d1, e1, a1, 14, 6);
|
||||||
|
R3a(a1, b1, c1, d1, e1, 4, 7);
|
||||||
|
R3a(e1, a1, b1, c1, d1, 9, 14);
|
||||||
|
R3a(d1, e1, a1, b1, c1, 15, 9);
|
||||||
|
R3a(c1, d1, e1, a1, b1, 8, 13);
|
||||||
|
R3a(b1, c1, d1, e1, a1, 1, 15);
|
||||||
|
R3a(a1, b1, c1, d1, e1, 2, 14);
|
||||||
|
R3a(e1, a1, b1, c1, d1, 7, 8);
|
||||||
|
R3a(d1, e1, a1, b1, c1, 0, 13);
|
||||||
|
R3a(c1, d1, e1, a1, b1, 6, 6);
|
||||||
|
R3a(b1, c1, d1, e1, a1, 13, 5);
|
||||||
|
R3a(a1, b1, c1, d1, e1, 11, 12);
|
||||||
|
R3a(e1, a1, b1, c1, d1, 5, 7);
|
||||||
|
R3a(d1, e1, a1, b1, c1, 12, 5);
|
||||||
|
|
||||||
|
// Left round 4
|
||||||
|
R4a(c1, d1, e1, a1, b1, 1, 11);
|
||||||
|
R4a(b1, c1, d1, e1, a1, 9, 12);
|
||||||
|
R4a(a1, b1, c1, d1, e1, 11, 14);
|
||||||
|
R4a(e1, a1, b1, c1, d1, 10, 15);
|
||||||
|
R4a(d1, e1, a1, b1, c1, 0, 14);
|
||||||
|
R4a(c1, d1, e1, a1, b1, 8, 15);
|
||||||
|
R4a(b1, c1, d1, e1, a1, 12, 9);
|
||||||
|
R4a(a1, b1, c1, d1, e1, 4, 8);
|
||||||
|
R4a(e1, a1, b1, c1, d1, 13, 9);
|
||||||
|
R4a(d1, e1, a1, b1, c1, 3, 14);
|
||||||
|
R4a(c1, d1, e1, a1, b1, 7, 5);
|
||||||
|
R4a(b1, c1, d1, e1, a1, 15, 6);
|
||||||
|
R4a(a1, b1, c1, d1, e1, 14, 8);
|
||||||
|
R4a(e1, a1, b1, c1, d1, 5, 6);
|
||||||
|
R4a(d1, e1, a1, b1, c1, 6, 5);
|
||||||
|
R4a(c1, d1, e1, a1, b1, 2, 12);
|
||||||
|
|
||||||
|
// Left round 5
|
||||||
|
R5a(b1, c1, d1, e1, a1, 4, 9);
|
||||||
|
R5a(a1, b1, c1, d1, e1, 0, 15);
|
||||||
|
R5a(e1, a1, b1, c1, d1, 5, 5);
|
||||||
|
R5a(d1, e1, a1, b1, c1, 9, 11);
|
||||||
|
R5a(c1, d1, e1, a1, b1, 7, 6);
|
||||||
|
R5a(b1, c1, d1, e1, a1, 12, 8);
|
||||||
|
R5a(a1, b1, c1, d1, e1, 2, 13);
|
||||||
|
R5a(e1, a1, b1, c1, d1, 10, 12);
|
||||||
|
R5a(d1, e1, a1, b1, c1, 14, 5);
|
||||||
|
R5a(c1, d1, e1, a1, b1, 1, 12);
|
||||||
|
R5a(b1, c1, d1, e1, a1, 3, 13);
|
||||||
|
R5a(a1, b1, c1, d1, e1, 8, 14);
|
||||||
|
R5a(e1, a1, b1, c1, d1, 11, 11);
|
||||||
|
R5a(d1, e1, a1, b1, c1, 6, 8);
|
||||||
|
R5a(c1, d1, e1, a1, b1, 15, 5);
|
||||||
|
R5a(b1, c1, d1, e1, a1, 13, 6);
|
||||||
|
|
||||||
|
// Right round 1
|
||||||
|
R1b(a2, b2, c2, d2, e2, 5, 8);
|
||||||
|
R1b(e2, a2, b2, c2, d2, 14, 9);
|
||||||
|
R1b(d2, e2, a2, b2, c2, 7, 9);
|
||||||
|
R1b(c2, d2, e2, a2, b2, 0, 11);
|
||||||
|
R1b(b2, c2, d2, e2, a2, 9, 13);
|
||||||
|
R1b(a2, b2, c2, d2, e2, 2, 15);
|
||||||
|
R1b(e2, a2, b2, c2, d2, 11, 15);
|
||||||
|
R1b(d2, e2, a2, b2, c2, 4, 5);
|
||||||
|
R1b(c2, d2, e2, a2, b2, 13, 7);
|
||||||
|
R1b(b2, c2, d2, e2, a2, 6, 7);
|
||||||
|
R1b(a2, b2, c2, d2, e2, 15, 8);
|
||||||
|
R1b(e2, a2, b2, c2, d2, 8, 11);
|
||||||
|
R1b(d2, e2, a2, b2, c2, 1, 14);
|
||||||
|
R1b(c2, d2, e2, a2, b2, 10, 14);
|
||||||
|
R1b(b2, c2, d2, e2, a2, 3, 12);
|
||||||
|
R1b(a2, b2, c2, d2, e2, 12, 6);
|
||||||
|
|
||||||
|
// Right round 2
|
||||||
|
R2b(e2, a2, b2, c2, d2, 6, 9);
|
||||||
|
R2b(d2, e2, a2, b2, c2, 11, 13);
|
||||||
|
R2b(c2, d2, e2, a2, b2, 3, 15);
|
||||||
|
R2b(b2, c2, d2, e2, a2, 7, 7);
|
||||||
|
R2b(a2, b2, c2, d2, e2, 0, 12);
|
||||||
|
R2b(e2, a2, b2, c2, d2, 13, 8);
|
||||||
|
R2b(d2, e2, a2, b2, c2, 5, 9);
|
||||||
|
R2b(c2, d2, e2, a2, b2, 10, 11);
|
||||||
|
R2b(b2, c2, d2, e2, a2, 14, 7);
|
||||||
|
R2b(a2, b2, c2, d2, e2, 15, 7);
|
||||||
|
R2b(e2, a2, b2, c2, d2, 8, 12);
|
||||||
|
R2b(d2, e2, a2, b2, c2, 12, 7);
|
||||||
|
R2b(c2, d2, e2, a2, b2, 4, 6);
|
||||||
|
R2b(b2, c2, d2, e2, a2, 9, 15);
|
||||||
|
R2b(a2, b2, c2, d2, e2, 1, 13);
|
||||||
|
R2b(e2, a2, b2, c2, d2, 2, 11);
|
||||||
|
|
||||||
|
// Right round 3
|
||||||
|
R3b(d2, e2, a2, b2, c2, 15, 9);
|
||||||
|
R3b(c2, d2, e2, a2, b2, 5, 7);
|
||||||
|
R3b(b2, c2, d2, e2, a2, 1, 15);
|
||||||
|
R3b(a2, b2, c2, d2, e2, 3, 11);
|
||||||
|
R3b(e2, a2, b2, c2, d2, 7, 8);
|
||||||
|
R3b(d2, e2, a2, b2, c2, 14, 6);
|
||||||
|
R3b(c2, d2, e2, a2, b2, 6, 6);
|
||||||
|
R3b(b2, c2, d2, e2, a2, 9, 14);
|
||||||
|
R3b(a2, b2, c2, d2, e2, 11, 12);
|
||||||
|
R3b(e2, a2, b2, c2, d2, 8, 13);
|
||||||
|
R3b(d2, e2, a2, b2, c2, 12, 5);
|
||||||
|
R3b(c2, d2, e2, a2, b2, 2, 14);
|
||||||
|
R3b(b2, c2, d2, e2, a2, 10, 13);
|
||||||
|
R3b(a2, b2, c2, d2, e2, 0, 13);
|
||||||
|
R3b(e2, a2, b2, c2, d2, 4, 7);
|
||||||
|
R3b(d2, e2, a2, b2, c2, 13, 5);
|
||||||
|
|
||||||
|
// Right round 4
|
||||||
|
R4b(c2, d2, e2, a2, b2, 8, 15);
|
||||||
|
R4b(b2, c2, d2, e2, a2, 6, 5);
|
||||||
|
R4b(a2, b2, c2, d2, e2, 4, 8);
|
||||||
|
R4b(e2, a2, b2, c2, d2, 1, 11);
|
||||||
|
R4b(d2, e2, a2, b2, c2, 3, 14);
|
||||||
|
R4b(c2, d2, e2, a2, b2, 11, 14);
|
||||||
|
R4b(b2, c2, d2, e2, a2, 15, 6);
|
||||||
|
R4b(a2, b2, c2, d2, e2, 0, 14);
|
||||||
|
R4b(e2, a2, b2, c2, d2, 5, 6);
|
||||||
|
R4b(d2, e2, a2, b2, c2, 12, 9);
|
||||||
|
R4b(c2, d2, e2, a2, b2, 2, 12);
|
||||||
|
R4b(b2, c2, d2, e2, a2, 13, 9);
|
||||||
|
R4b(a2, b2, c2, d2, e2, 9, 12);
|
||||||
|
R4b(e2, a2, b2, c2, d2, 7, 5);
|
||||||
|
R4b(d2, e2, a2, b2, c2, 10, 15);
|
||||||
|
R4b(c2, d2, e2, a2, b2, 14, 8);
|
||||||
|
|
||||||
|
// Right round 5
|
||||||
|
R5b(b2, c2, d2, e2, a2, 12 , 8);
|
||||||
|
R5b(a2, b2, c2, d2, e2, 15 , 5);
|
||||||
|
R5b(e2, a2, b2, c2, d2, 10 , 12);
|
||||||
|
R5b(d2, e2, a2, b2, c2, 4 , 9);
|
||||||
|
R5b(c2, d2, e2, a2, b2, 1 , 12);
|
||||||
|
R5b(b2, c2, d2, e2, a2, 5 , 5);
|
||||||
|
R5b(a2, b2, c2, d2, e2, 8 , 14);
|
||||||
|
R5b(e2, a2, b2, c2, d2, 7 , 6);
|
||||||
|
R5b(d2, e2, a2, b2, c2, 6 , 8);
|
||||||
|
R5b(c2, d2, e2, a2, b2, 2 , 13);
|
||||||
|
R5b(b2, c2, d2, e2, a2, 13 , 6);
|
||||||
|
R5b(a2, b2, c2, d2, e2, 14 , 5);
|
||||||
|
R5b(e2, a2, b2, c2, d2, 0 , 15);
|
||||||
|
R5b(d2, e2, a2, b2, c2, 3 , 13);
|
||||||
|
R5b(c2, d2, e2, a2, b2, 9 , 11);
|
||||||
|
R5b(b2, c2, d2, e2, a2, 11 , 11);
|
||||||
|
|
||||||
|
// Finalise state
|
||||||
|
d2 = m_state[1] + c1 + d2;
|
||||||
|
m_state[1] = m_state[2] + d1 + e2;
|
||||||
|
m_state[2] = m_state[3] + e1 + a2;
|
||||||
|
m_state[3] = m_state[4] + a1 + b2;
|
||||||
|
m_state[4] = m_state[0] + b1 + c2;
|
||||||
|
m_state[0] = d2;
|
||||||
|
|
||||||
|
m_buffer.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
RIPEMD::finish (void) {
|
||||||
|
// Ensure the length wouldn't overflow if converted to bits. We need to
|
||||||
|
// grab this before there's a chance it gets overwritten.
|
||||||
|
CHECK_EQ (m_length >> sizeof(m_length) * 8 - 3, 0);
|
||||||
|
uint64_t length = m_length * 8;
|
||||||
|
|
||||||
|
// Push a padding byte into the buffer
|
||||||
|
uint8_t padding = 0x80;
|
||||||
|
update (&padding, 1);
|
||||||
|
|
||||||
|
// Pad out the line if we couldn't fit a length at the end
|
||||||
|
size_t remaining = sizeof (m_buffer.d32) - m_buffer.size;
|
||||||
|
if (remaining < 8) {
|
||||||
|
static const uint8_t ZEROES[8] = { 0 };
|
||||||
|
|
||||||
|
update (ZEROES, remaining);
|
||||||
|
|
||||||
|
CHECK_EQ (m_buffer.size, 0);
|
||||||
|
remaining = sizeof (m_buffer.d08);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the length to the end of the buffer
|
||||||
|
union {
|
||||||
|
uint32_t d32[16];
|
||||||
|
uint8_t d08[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
memset (d32, 0, sizeof (d32));
|
||||||
|
d32[14] = length & 0xFFFFFFFF;
|
||||||
|
d32[15] = length >> 32u;
|
||||||
|
|
||||||
|
// Do the final update
|
||||||
|
size_t offset = sizeof(d08) - remaining;
|
||||||
|
update (d08 + offset, remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
RIPEMD::digest_t
|
||||||
|
RIPEMD::digest (void) const {
|
||||||
|
digest_t d;
|
||||||
|
memcpy (d.data (), m_state, sizeof (m_state));
|
||||||
|
return d;
|
||||||
|
}
|
47
hash/ripemd.hpp
Normal file
47
hash/ripemd.hpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of libgim
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* Copyright 2014 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UTIL_HASH_RIPEMD_HPP
|
||||||
|
#define __UTIL_HASH_RIPEMD_HPP
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
namespace hash {
|
||||||
|
class RIPEMD {
|
||||||
|
public:
|
||||||
|
typedef std::array<uint8_t,20> digest_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RIPEMD();
|
||||||
|
|
||||||
|
void update(const uint8_t*, size_t);
|
||||||
|
void finish(void);
|
||||||
|
digest_t digest(void) const;
|
||||||
|
void reset(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void transform ();
|
||||||
|
|
||||||
|
uint32_t m_state[5];
|
||||||
|
uint64_t m_length;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
union {
|
||||||
|
uint32_t d32[16];
|
||||||
|
uint8_t d08[64];
|
||||||
|
};
|
||||||
|
size_t size;
|
||||||
|
} m_buffer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
1
test/.gitignore
vendored
1
test/.gitignore
vendored
@ -15,6 +15,7 @@
|
|||||||
/pool*
|
/pool*
|
||||||
/random*
|
/random*
|
||||||
/range*
|
/range*
|
||||||
|
/ripemd
|
||||||
/region*
|
/region*
|
||||||
/sha1*
|
/sha1*
|
||||||
/signal*
|
/signal*
|
||||||
|
@ -20,6 +20,7 @@ TEST_BIN = \
|
|||||||
rand \
|
rand \
|
||||||
range \
|
range \
|
||||||
region \
|
region \
|
||||||
|
ripemd \
|
||||||
signal \
|
signal \
|
||||||
sha1 \
|
sha1 \
|
||||||
version
|
version
|
||||||
|
136
test/ripemd.cpp
Normal file
136
test/ripemd.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include "../debug.hpp"
|
||||||
|
#include "../types.hpp"
|
||||||
|
#include "../hash/ripemd.hpp"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using util::hash::RIPEMD;
|
||||||
|
|
||||||
|
static const
|
||||||
|
struct {
|
||||||
|
const char *input;
|
||||||
|
RIPEMD::digest_t output;
|
||||||
|
} TESTS[] = {
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
{ 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
|
||||||
|
0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 },
|
||||||
|
// 128: cdf26213a150dc3ecb610f18f6b38b46
|
||||||
|
// 160: 9c1185a5c5e9fc54612808977ee8f548b2258d31
|
||||||
|
// 256: 02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d
|
||||||
|
// 320: 22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"a",
|
||||||
|
{ 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
|
||||||
|
0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe },
|
||||||
|
// 128: 86be7afa339d0fc7cfc785e72f578d33
|
||||||
|
// 160: 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe
|
||||||
|
// 256: f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925
|
||||||
|
// 320: ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"abc",
|
||||||
|
{ 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
|
||||||
|
0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc },
|
||||||
|
// 128: c14a12199c66e4ba84636b0f69144c77
|
||||||
|
// 160: 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
|
||||||
|
// 256: afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65
|
||||||
|
// 320: de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"message digest",
|
||||||
|
{ 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
|
||||||
|
0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 },
|
||||||
|
// 128: 9e327b3d6e523062afc1132d7df9d1b8
|
||||||
|
// 160: 5d0689ef49d2fae572b881b123a85ffa21595f36
|
||||||
|
// 256: 87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e
|
||||||
|
// 320: 3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"abcdefghijklmnopqrstuvwxyz",
|
||||||
|
{ 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
|
||||||
|
0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc },
|
||||||
|
// 128: fd2aa607f71dc8f510714922b371834e
|
||||||
|
// 160: f71c27109c692c1b56bbdceb5b9d2865b3708dbc
|
||||||
|
// 256: 649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133
|
||||||
|
// 320: cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||||
|
{ 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
|
||||||
|
0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b },
|
||||||
|
// 128: a1aa0689d0fafa2ddc22e88b49133a06
|
||||||
|
// 160: 12a053384a9c0c88e405a06c27dcf49ada62eb2b
|
||||||
|
// 256: 3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f
|
||||||
|
// 320: d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||||
|
{ 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed,
|
||||||
|
0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 },
|
||||||
|
// 128: d1e959eb179c911faea4624c60c5c702
|
||||||
|
// 160: b0e20b6e3116640286ed3a87a5713079b21f5189
|
||||||
|
// 256: 5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8
|
||||||
|
// 320: ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||||
|
{ 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb,
|
||||||
|
0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }
|
||||||
|
// 128: 3f45ef194732c2dbb2c4a2c769795fa3
|
||||||
|
// 160: 9b752e45573d4b39f4dbd3323cab82bf63326bfb
|
||||||
|
// 256: 06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd
|
||||||
|
// 320: 557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 1 million times "a"
|
||||||
|
// 128: 4a7f5723f954eba1216c9d8f6320431f
|
||||||
|
// 160: 52783243c1697bdbe16d37f97f68f08325dc1528
|
||||||
|
// 256: ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978
|
||||||
|
// 320: bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int, char**) {
|
||||||
|
// Check against simple test vectors
|
||||||
|
for (size_t i = 0; i < elems (TESTS); ++i) {
|
||||||
|
std::cout << "testing '" << TESTS[i].input << "'\n";
|
||||||
|
|
||||||
|
util::hash::RIPEMD obj;
|
||||||
|
obj.update (reinterpret_cast<const uint8_t*> (TESTS[i].input),
|
||||||
|
strlen (TESTS[i].input));
|
||||||
|
obj.finish ();
|
||||||
|
|
||||||
|
CHECK_HARD (obj.digest () == TESTS[i].output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform 'million-a' check
|
||||||
|
static const size_t CHUNK_WIDTH = 1000;
|
||||||
|
util::hash::RIPEMD obj;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 1000000; i += CHUNK_WIDTH) {
|
||||||
|
uint8_t data[CHUNK_WIDTH];
|
||||||
|
memset (data, 'a', sizeof (data));
|
||||||
|
|
||||||
|
obj.update (data, sizeof (data));
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.finish ();
|
||||||
|
static const util::hash::RIPEMD::digest_t MILLION {
|
||||||
|
0x52, 0x78, 0x32, 0x43, 0xc1, 0x69, 0x7b, 0xdb, 0xe1, 0x6d,
|
||||||
|
0x37, 0xf9, 0x7f, 0x68, 0xf0, 0x83, 0x25, 0xdc, 0x15, 0x28
|
||||||
|
};
|
||||||
|
CHECK_HARD (obj.digest () == MILLION);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user