keyhunt/hash/ripemd160.cpp
2021-10-25 19:38:06 +02:00

317 lines
10 KiB
C++

/*
* This file is part of the VanitySearch distribution (https://github.com/JeanLucPons/VanitySearch).
* Copyright (c) 2019 Jean Luc PONS.
*
* 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, version 3.
*
* 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/>.
*/
#include "ripemd160.h"
#include <string.h>
/// Internal RIPEMD-160 implementation.
namespace _ripemd160 {
/** Initialize RIPEMD-160 state. */
void inline Initialize(uint32_t* s)
{
s[0] = 0x67452301ul;
s[1] = 0xEFCDAB89ul;
s[2] = 0x98BADCFEul;
s[3] = 0x10325476ul;
s[4] = 0xC3D2E1F0ul;
}
#ifndef WIN64
inline uint32_t _rotl(uint32_t x, uint8_t r) {
asm("roll %1,%0" : "+r" (x) : "c" (r));
return x;
}
#endif
#define ROL(x,n) _rotl(x,n)
#define f1(x, y, z) (x ^ y ^ z)
#define f2(x, y, z) ((x & y) | (~x & z))
#define f3(x, y, z) ((x | ~y) ^ z)
#define f4(x, y, z) ((x & z) | (~z & y))
#define f5(x, y, z) (x ^ (y | ~z))
#define Round(a,b,c,d,e,f,x,k,r) \
a = ROL(a + f + x + k, r) + e; \
c = ROL(c, 10);
#define R11(a,b,c,d,e,x,r) Round(a, b, c, d, e, f1(b, c, d), x, 0, r)
#define R21(a,b,c,d,e,x,r) Round(a, b, c, d, e, f2(b, c, d), x, 0x5A827999ul, r)
#define R31(a,b,c,d,e,x,r) Round(a, b, c, d, e, f3(b, c, d), x, 0x6ED9EBA1ul, r)
#define R41(a,b,c,d,e,x,r) Round(a, b, c, d, e, f4(b, c, d), x, 0x8F1BBCDCul, r)
#define R51(a,b,c,d,e,x,r) Round(a, b, c, d, e, f5(b, c, d), x, 0xA953FD4Eul, r)
#define R12(a,b,c,d,e,x,r) Round(a, b, c, d, e, f5(b, c, d), x, 0x50A28BE6ul, r)
#define R22(a,b,c,d,e,x,r) Round(a, b, c, d, e, f4(b, c, d), x, 0x5C4DD124ul, r)
#define R32(a,b,c,d,e,x,r) Round(a, b, c, d, e, f3(b, c, d), x, 0x6D703EF3ul, r)
#define R42(a,b,c,d,e,x,r) Round(a, b, c, d, e, f2(b, c, d), x, 0x7A6D76E9ul, r)
#define R52(a,b,c,d,e,x,r) Round(a, b, c, d, e, f1(b, c, d), x, 0, r)
/** Perform a RIPEMD-160 transformation, processing a 64-byte chunk. */
void Transform(uint32_t* s, const unsigned char* chunk)
{
uint32_t a1 = s[0], b1 = s[1], c1 = s[2], d1 = s[3], e1 = s[4];
uint32_t a2 = a1, b2 = b1, c2 = c1, d2 = d1, e2 = e1;
uint32_t w[16];
memcpy(w,chunk,16*sizeof(uint32_t));
R11(a1, b1, c1, d1, e1, w[0], 11);
R12(a2, b2, c2, d2, e2, w[5], 8);
R11(e1, a1, b1, c1, d1, w[1], 14);
R12(e2, a2, b2, c2, d2, w[14], 9);
R11(d1, e1, a1, b1, c1, w[2], 15);
R12(d2, e2, a2, b2, c2, w[7], 9);
R11(c1, d1, e1, a1, b1, w[3], 12);
R12(c2, d2, e2, a2, b2, w[0], 11);
R11(b1, c1, d1, e1, a1, w[4], 5);
R12(b2, c2, d2, e2, a2, w[9], 13);
R11(a1, b1, c1, d1, e1, w[5], 8);
R12(a2, b2, c2, d2, e2, w[2], 15);
R11(e1, a1, b1, c1, d1, w[6], 7);
R12(e2, a2, b2, c2, d2, w[11], 15);
R11(d1, e1, a1, b1, c1, w[7], 9);
R12(d2, e2, a2, b2, c2, w[4], 5);
R11(c1, d1, e1, a1, b1, w[8], 11);
R12(c2, d2, e2, a2, b2, w[13], 7);
R11(b1, c1, d1, e1, a1, w[9], 13);
R12(b2, c2, d2, e2, a2, w[6], 7);
R11(a1, b1, c1, d1, e1, w[10], 14);
R12(a2, b2, c2, d2, e2, w[15], 8);
R11(e1, a1, b1, c1, d1, w[11], 15);
R12(e2, a2, b2, c2, d2, w[8], 11);
R11(d1, e1, a1, b1, c1, w[12], 6);
R12(d2, e2, a2, b2, c2, w[1], 14);
R11(c1, d1, e1, a1, b1, w[13], 7);
R12(c2, d2, e2, a2, b2, w[10], 14);
R11(b1, c1, d1, e1, a1, w[14], 9);
R12(b2, c2, d2, e2, a2, w[3], 12);
R11(a1, b1, c1, d1, e1, w[15], 8);
R12(a2, b2, c2, d2, e2, w[12], 6);
R21(e1, a1, b1, c1, d1, w[7], 7);
R22(e2, a2, b2, c2, d2, w[6], 9);
R21(d1, e1, a1, b1, c1, w[4], 6);
R22(d2, e2, a2, b2, c2, w[11], 13);
R21(c1, d1, e1, a1, b1, w[13], 8);
R22(c2, d2, e2, a2, b2, w[3], 15);
R21(b1, c1, d1, e1, a1, w[1], 13);
R22(b2, c2, d2, e2, a2, w[7], 7);
R21(a1, b1, c1, d1, e1, w[10], 11);
R22(a2, b2, c2, d2, e2, w[0], 12);
R21(e1, a1, b1, c1, d1, w[6], 9);
R22(e2, a2, b2, c2, d2, w[13], 8);
R21(d1, e1, a1, b1, c1, w[15], 7);
R22(d2, e2, a2, b2, c2, w[5], 9);
R21(c1, d1, e1, a1, b1, w[3], 15);
R22(c2, d2, e2, a2, b2, w[10], 11);
R21(b1, c1, d1, e1, a1, w[12], 7);
R22(b2, c2, d2, e2, a2, w[14], 7);
R21(a1, b1, c1, d1, e1, w[0], 12);
R22(a2, b2, c2, d2, e2, w[15], 7);
R21(e1, a1, b1, c1, d1, w[9], 15);
R22(e2, a2, b2, c2, d2, w[8], 12);
R21(d1, e1, a1, b1, c1, w[5], 9);
R22(d2, e2, a2, b2, c2, w[12], 7);
R21(c1, d1, e1, a1, b1, w[2], 11);
R22(c2, d2, e2, a2, b2, w[4], 6);
R21(b1, c1, d1, e1, a1, w[14], 7);
R22(b2, c2, d2, e2, a2, w[9], 15);
R21(a1, b1, c1, d1, e1, w[11], 13);
R22(a2, b2, c2, d2, e2, w[1], 13);
R21(e1, a1, b1, c1, d1, w[8], 12);
R22(e2, a2, b2, c2, d2, w[2], 11);
R31(d1, e1, a1, b1, c1, w[3], 11);
R32(d2, e2, a2, b2, c2, w[15], 9);
R31(c1, d1, e1, a1, b1, w[10], 13);
R32(c2, d2, e2, a2, b2, w[5], 7);
R31(b1, c1, d1, e1, a1, w[14], 6);
R32(b2, c2, d2, e2, a2, w[1], 15);
R31(a1, b1, c1, d1, e1, w[4], 7);
R32(a2, b2, c2, d2, e2, w[3], 11);
R31(e1, a1, b1, c1, d1, w[9], 14);
R32(e2, a2, b2, c2, d2, w[7], 8);
R31(d1, e1, a1, b1, c1, w[15], 9);
R32(d2, e2, a2, b2, c2, w[14], 6);
R31(c1, d1, e1, a1, b1, w[8], 13);
R32(c2, d2, e2, a2, b2, w[6], 6);
R31(b1, c1, d1, e1, a1, w[1], 15);
R32(b2, c2, d2, e2, a2, w[9], 14);
R31(a1, b1, c1, d1, e1, w[2], 14);
R32(a2, b2, c2, d2, e2, w[11], 12);
R31(e1, a1, b1, c1, d1, w[7], 8);
R32(e2, a2, b2, c2, d2, w[8], 13);
R31(d1, e1, a1, b1, c1, w[0], 13);
R32(d2, e2, a2, b2, c2, w[12], 5);
R31(c1, d1, e1, a1, b1, w[6], 6);
R32(c2, d2, e2, a2, b2, w[2], 14);
R31(b1, c1, d1, e1, a1, w[13], 5);
R32(b2, c2, d2, e2, a2, w[10], 13);
R31(a1, b1, c1, d1, e1, w[11], 12);
R32(a2, b2, c2, d2, e2, w[0], 13);
R31(e1, a1, b1, c1, d1, w[5], 7);
R32(e2, a2, b2, c2, d2, w[4], 7);
R31(d1, e1, a1, b1, c1, w[12], 5);
R32(d2, e2, a2, b2, c2, w[13], 5);
R41(c1, d1, e1, a1, b1, w[1], 11);
R42(c2, d2, e2, a2, b2, w[8], 15);
R41(b1, c1, d1, e1, a1, w[9], 12);
R42(b2, c2, d2, e2, a2, w[6], 5);
R41(a1, b1, c1, d1, e1, w[11], 14);
R42(a2, b2, c2, d2, e2, w[4], 8);
R41(e1, a1, b1, c1, d1, w[10], 15);
R42(e2, a2, b2, c2, d2, w[1], 11);
R41(d1, e1, a1, b1, c1, w[0], 14);
R42(d2, e2, a2, b2, c2, w[3], 14);
R41(c1, d1, e1, a1, b1, w[8], 15);
R42(c2, d2, e2, a2, b2, w[11], 14);
R41(b1, c1, d1, e1, a1, w[12], 9);
R42(b2, c2, d2, e2, a2, w[15], 6);
R41(a1, b1, c1, d1, e1, w[4], 8);
R42(a2, b2, c2, d2, e2, w[0], 14);
R41(e1, a1, b1, c1, d1, w[13], 9);
R42(e2, a2, b2, c2, d2, w[5], 6);
R41(d1, e1, a1, b1, c1, w[3], 14);
R42(d2, e2, a2, b2, c2, w[12], 9);
R41(c1, d1, e1, a1, b1, w[7], 5);
R42(c2, d2, e2, a2, b2, w[2], 12);
R41(b1, c1, d1, e1, a1, w[15], 6);
R42(b2, c2, d2, e2, a2, w[13], 9);
R41(a1, b1, c1, d1, e1, w[14], 8);
R42(a2, b2, c2, d2, e2, w[9], 12);
R41(e1, a1, b1, c1, d1, w[5], 6);
R42(e2, a2, b2, c2, d2, w[7], 5);
R41(d1, e1, a1, b1, c1, w[6], 5);
R42(d2, e2, a2, b2, c2, w[10], 15);
R41(c1, d1, e1, a1, b1, w[2], 12);
R42(c2, d2, e2, a2, b2, w[14], 8);
R51(b1, c1, d1, e1, a1, w[4], 9);
R52(b2, c2, d2, e2, a2, w[12], 8);
R51(a1, b1, c1, d1, e1, w[0], 15);
R52(a2, b2, c2, d2, e2, w[15], 5);
R51(e1, a1, b1, c1, d1, w[5], 5);
R52(e2, a2, b2, c2, d2, w[10], 12);
R51(d1, e1, a1, b1, c1, w[9], 11);
R52(d2, e2, a2, b2, c2, w[4], 9);
R51(c1, d1, e1, a1, b1, w[7], 6);
R52(c2, d2, e2, a2, b2, w[1], 12);
R51(b1, c1, d1, e1, a1, w[12], 8);
R52(b2, c2, d2, e2, a2, w[5], 5);
R51(a1, b1, c1, d1, e1, w[2], 13);
R52(a2, b2, c2, d2, e2, w[8], 14);
R51(e1, a1, b1, c1, d1, w[10], 12);
R52(e2, a2, b2, c2, d2, w[7], 6);
R51(d1, e1, a1, b1, c1, w[14], 5);
R52(d2, e2, a2, b2, c2, w[6], 8);
R51(c1, d1, e1, a1, b1, w[1], 12);
R52(c2, d2, e2, a2, b2, w[2], 13);
R51(b1, c1, d1, e1, a1, w[3], 13);
R52(b2, c2, d2, e2, a2, w[13], 6);
R51(a1, b1, c1, d1, e1, w[8], 14);
R52(a2, b2, c2, d2, e2, w[14], 5);
R51(e1, a1, b1, c1, d1, w[11], 11);
R52(e2, a2, b2, c2, d2, w[0], 15);
R51(d1, e1, a1, b1, c1, w[6], 8);
R52(d2, e2, a2, b2, c2, w[3], 13);
R51(c1, d1, e1, a1, b1, w[15], 5);
R52(c2, d2, e2, a2, b2, w[9], 11);
R51(b1, c1, d1, e1, a1, w[13], 6);
R52(b2, c2, d2, e2, a2, w[11], 11);
uint32_t t = s[0];
s[0] = s[1] + c1 + d2;
s[1] = s[2] + d1 + e2;
s[2] = s[3] + e1 + a2;
s[3] = s[4] + a1 + b2;
s[4] = t + b1 + c2;
}
} // namespace ripemd160
CRIPEMD160::CRIPEMD160() : bytes(0)
{
_ripemd160::Initialize(s);
}
void CRIPEMD160::Write(const unsigned char* data, size_t len)
{
const unsigned char* end = data + len;
size_t bufsize = bytes % 64;
if (bufsize && bufsize + len >= 64) {
// Fill the buffer, and process it.
memcpy(buf + bufsize, data, 64 - bufsize);
bytes += 64 - bufsize;
data += 64 - bufsize;
_ripemd160::Transform(s, buf);
bufsize = 0;
}
while (end >= data + 64) {
// Process full chunks directly from the source.
_ripemd160::Transform(s, data);
bytes += 64;
data += 64;
}
if (end > data) {
// Fill the buffer with what remains.
memcpy(buf + bufsize, data, end - data);
bytes += end - data;
}
}
void CRIPEMD160::Finalize(unsigned char hash[20])
{
static const unsigned char pad[64] = {0x80};
unsigned char sizedesc[8];
*(uint64_t *)sizedesc = bytes << 3;
Write(pad, 1 + ((119 - (bytes % 64)) % 64));
Write(sizedesc, 8);
memcpy(hash,s,20);
}
static const uint64_t sizedesc_32 = 32 << 3;
static const unsigned char pad[64] = { 0x80 };
void ripemd160_32(unsigned char *input, unsigned char *digest) {
uint32_t *s = (uint32_t *)digest;
_ripemd160::Initialize(s);
memcpy(input+32,pad,24);
memcpy(input+56,&sizedesc_32,8);
_ripemd160::Transform(s, input);
}
void ripemd160(unsigned char *input,int length,unsigned char *digest) {
CRIPEMD160 cripe;
cripe.Write(input,length);
cripe.Finalize(digest);
}
std::string ripemd160_hex(unsigned char *digest) {
char buf[2 * 20 + 1];
buf[2 * 20] = 0;
for (int i = 0; i < 20; i++)
sprintf(buf + i * 2, "%02x", (int)digest[i]);
return std::string(buf);
}