Skip to content

Commit

Permalink
use fixed width ripemd160
Browse files Browse the repository at this point in the history
  • Loading branch information
ryancdotorg committed Oct 24, 2015
1 parent cfd1d09 commit 2ab38f5
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
HEADERS = bloom.h crack.h hash160.h warpwallet.h
OBJ_MAIN = brainflayer.o hex2blf.o blfchk.o ecmtabgen.o
OBJ_UTIL = hex.o bloom.o mmapf.o hsearchf.o ec_pubkey_fast.o dldummy.o
OBJ_UTIL = hex.o bloom.o mmapf.o hsearchf.o ec_pubkey_fast.o ripemd160_256.o dldummy.o
OBJ_FMT = warpwallet.o brainwalletio.o brainv2.o
OBJECTS = $(OBJ_MAIN) $(OBJ_UTIL) $(OBJ_FMT)
BINARIES = brainflayer hex2blf blfchk ecmtabgen
Expand Down
19 changes: 4 additions & 15 deletions brainflayer.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

#include "secp256k1/include/secp256k1.h"

#include "ripemd160_256.h"

#include "ec_pubkey_fast.h"

#include "hex.h"
Expand All @@ -39,7 +41,6 @@ static int brainflayer_is_init = 0;

static unsigned char hash256[SHA256_DIGEST_LENGTH];
static unsigned char priv256[SHA256_DIGEST_LENGTH];
static hash160_t hash160_tmp;
static hash160_t hash160_compr;
static hash160_t hash160_uncmp;
static unsigned char *mem;
Expand All @@ -50,7 +51,6 @@ static unsigned char *bloom = NULL;
static unsigned char hexed[4096], unhexed[4096];

static SHA256_CTX *sha256_ctx;
static RIPEMD160_CTX *ripemd160_ctx;

static secp256k1_context_t *secp256k1_ctx;
static secp256k1_pubkey_t *pubkey;
Expand Down Expand Up @@ -78,7 +78,6 @@ static inline void brainflayer_init_globals() {

/* initialize hashs */
sha256_ctx = malloc(sizeof(*sha256_ctx));
ripemd160_ctx = malloc(sizeof(*ripemd160_ctx));
/* initialize pubkey struct */
pubkey = malloc(sizeof(*pubkey));

Expand Down Expand Up @@ -109,12 +108,7 @@ inline static int priv2hash160(unsigned char *priv) {
SHA256_Update(sha256_ctx, pub_chr, 65);
SHA256_Final(hash256, sha256_ctx);
/* ripemd160(sha256(pub)) */
RIPEMD160_Init(ripemd160_ctx);
RIPEMD160_Update(ripemd160_ctx, hash256, SHA256_DIGEST_LENGTH);
RIPEMD160_Final(hash160_tmp.uc, ripemd160_ctx);

/* save result to global struct */
memcpy(hash160_uncmp.uc, hash160_tmp.uc, 20);
ripemd160_256(hash256, hash160_uncmp.uc);

/* quick and dirty public key compression */
pub_chr[0] = 0x02 | (pub_chr[64] & 0x01);
Expand All @@ -125,12 +119,7 @@ inline static int priv2hash160(unsigned char *priv) {
SHA256_Update(sha256_ctx, pub_chr, 33);
SHA256_Final(hash256, sha256_ctx);
/* ripemd160(sha256(pub)) */
RIPEMD160_Init(ripemd160_ctx);
RIPEMD160_Update(ripemd160_ctx, hash256, SHA256_DIGEST_LENGTH);
RIPEMD160_Final(hash160_tmp.uc, ripemd160_ctx);

/* save result to global struct */
memcpy(hash160_compr.uc, hash160_tmp.uc, 20);
ripemd160_256(hash256, hash160_compr.uc);

return 0;
}
Expand Down
286 changes: 286 additions & 0 deletions ripemd160_256.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
#define _RIPEMD160_C_ 1

#include "ripemd160_256.h"

// adapted by Pieter Wuille in 2012; all changes are in the public domain
// modified by Ryan Castellucci in 2015; all changes are in the public domain

/*
*
* RIPEMD160.c : RIPEMD-160 implementation
*
* Written in 2008 by Dwayne C. Litzenberger <[email protected]>
*
* ===================================================================
* The contents of this file are dedicated to the public domain. To
* the extent that dedication to the public domain is not available,
* everyone is granted a worldwide, perpetual, royalty-free,
* non-exclusive license to exercise all rights associated with the
* contents of this file for any purpose whatsoever.
* No rights are reserved.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* ===================================================================
*
* Country of origin: Canada
*
* This implementation (written in C) is based on an implementation the author
* wrote in Python.
*
* This implementation was written with reference to the RIPEMD-160
* specification, which is available at:
* http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/
*
* It is also documented in the _Handbook of Applied Cryptography_, as
* Algorithm 9.55. It's on page 30 of the following PDF file:
* http://www.cacr.math.uwaterloo.ca/hac/about/chap9.pdf
*
* The RIPEMD-160 specification doesn't really tell us how to do padding, but
* since RIPEMD-160 is inspired by MD4, you can use the padding algorithm from
* RFC 1320.
*
* According to http://www.users.zetnet.co.uk/hopwood/crypto/scan/md.html:
* "RIPEMD-160 is big-bit-endian, little-byte-endian, and left-justified."
*/

#include <stdint.h>

#include <string.h>

#define RIPEMD160_DIGEST_SIZE 20
#define BLOCK_SIZE 64

/* cyclic left-shift the 32-bit word n left by s bits */
#define ROL(s, n) (((n) << (s)) | ((n) >> (32-(s))))

/* Initial values for the chaining variables.
* This is just 0123456789ABCDEFFEDCBA9876543210F0E1D2C3 in little-endian. */
static const uint32_t initial_h[5] = { 0x67452301u, 0xEFCDAB89u, 0x98BADCFEu, 0x10325476u, 0xC3D2E1F0u };

/* Ordering of message words. Based on the permutations rho(i) and pi(i), defined as follows:
*
* rho(i) := { 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 }[i] 0 <= i <= 15
*
* pi(i) := 9*i + 5 (mod 16)
*
* Line | Round 1 | Round 2 | Round 3 | Round 4 | Round 5
* -------+-----------+-----------+-----------+-----------+-----------
* left | id | rho | rho^2 | rho^3 | rho^4
* right | pi | rho pi | rho^2 pi | rho^3 pi | rho^4 pi
*/

/* Left line */
static const uint8_t RL[5][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* Round 1: id */
{ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 }, /* Round 2: rho */
{ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 }, /* Round 3: rho^2 */
{ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 }, /* Round 4: rho^3 */
{ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 } /* Round 5: rho^4 */
};

/* Right line */
static const uint8_t RR[5][16] = {
{ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 }, /* Round 1: pi */
{ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 }, /* Round 2: rho pi */
{ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 }, /* Round 3: rho^2 pi */
{ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 }, /* Round 4: rho^3 pi */
{ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 } /* Round 5: rho^4 pi */
};

/*
* Shifts - Since we don't actually re-order the message words according to
* the permutations above (we could, but it would be slower), these tables
* come with the permutations pre-applied.
*/

/* Shifts, left line */
static const uint8_t SL[5][16] = {
{ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 }, /* Round 1 */
{ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 }, /* Round 2 */
{ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 }, /* Round 3 */
{ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 }, /* Round 4 */
{ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 } /* Round 5 */
};

/* Shifts, right line */
static const uint8_t SR[5][16] = {
{ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 }, /* Round 1 */
{ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 }, /* Round 2 */
{ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 }, /* Round 3 */
{ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 }, /* Round 4 */
{ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 } /* Round 5 */
};

/* static padding for 256 bit input */
static const uint8_t pad256[32] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* length 256 bits, little endian uint64_t */
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/* Boolean functions */

#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)) | ((y) & ~(z)))
#define F5(x, y, z) ((x) ^ ((y) | ~(z)))

/* Round constants, left line */
static const uint32_t KL[5] = {
0x00000000u, /* Round 1: 0 */
0x5A827999u, /* Round 2: floor(2**30 * sqrt(2)) */
0x6ED9EBA1u, /* Round 3: floor(2**30 * sqrt(3)) */
0x8F1BBCDCu, /* Round 4: floor(2**30 * sqrt(5)) */
0xA953FD4Eu /* Round 5: floor(2**30 * sqrt(7)) */
};

/* Round constants, right line */
static const uint32_t KR[5] = {
0x50A28BE6u, /* Round 1: floor(2**30 * cubert(2)) */
0x5C4DD124u, /* Round 2: floor(2**30 * cubert(3)) */
0x6D703EF3u, /* Round 3: floor(2**30 * cubert(5)) */
0x7A6D76E9u, /* Round 4: floor(2**30 * cubert(7)) */
0x00000000u /* Round 5: 0 */
};

static inline void byteswap32(uint32_t *v)
{
union { uint32_t w; uint8_t b[4]; } x, y;

x.w = *v;
y.b[0] = x.b[3];
y.b[1] = x.b[2];
y.b[2] = x.b[1];
y.b[3] = x.b[0];
*v = y.w;

/* Wipe temporary variables */
x.w = y.w = 0;
}

static inline void byteswap_digest(uint32_t *p)
{
unsigned int i;

for (i = 0; i < 4; i++) {
byteswap32(p++);
byteswap32(p++);
byteswap32(p++);
byteswap32(p++);
}
}

/* The RIPEMD160 compression function. */
static inline void ripemd160_rawcompress(void *pbuf, void *ph)
{
uint8_t w, round;
uint32_t T;
uint32_t AL, BL, CL, DL, EL; /* left line */
uint32_t AR, BR, CR, DR, ER; /* right line */

uint32_t *buf = pbuf;
uint32_t *h = ph;

/* Byte-swap the buffer if we're on a big-endian machine */
#ifdef PCT_BIG_ENDIAN
byteswap_digest(buf);
#endif

/* initialize state */
memcpy(h, initial_h, RIPEMD160_DIGEST_SIZE);

/* Load the left and right lines with the initial state */
AL = AR = h[0];
BL = BR = h[1];
CL = CR = h[2];
DL = DR = h[3];
EL = ER = h[4];

/* Round 1 */
round = 0;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F1(BL, CL, DL) + buf[RL[round][w]] + KL[round]) + EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F5(BR, CR, DR) + buf[RR[round][w]] + KR[round]) + ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}

/* Round 2 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F2(BL, CL, DL) + buf[RL[round][w]] + KL[round]) + EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F4(BR, CR, DR) + buf[RR[round][w]] + KR[round]) + ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}

/* Round 3 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F3(BL, CL, DL) + buf[RL[round][w]] + KL[round]) + EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F3(BR, CR, DR) + buf[RR[round][w]] + KR[round]) + ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}

/* Round 4 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F4(BL, CL, DL) + buf[RL[round][w]] + KL[round]) + EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F2(BR, CR, DR) + buf[RR[round][w]] + KR[round]) + ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}

/* Round 5 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F5(BL, CL, DL) + buf[RL[round][w]] + KL[round]) + EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F1(BR, CR, DR) + buf[RR[round][w]] + KR[round]) + ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}

/* Final mixing stage */
T = h[1] + CL + DR;
h[1] = h[2] + DL + ER;
h[2] = h[3] + EL + AR;
h[3] = h[4] + AL + BR;
h[4] = h[0] + BL + CR;
h[0] = T;

/* Byte-swap the output if we're on a big-endian machine */
#ifdef PCT_BIG_ENDIAN
byteswap_digest(h);
#endif
}

void ripemd160_256(const void *in, void *out) {
unsigned char buf[64];
/* copy input data */
memcpy(buf + 0, in, 32);
/* append fixed padding */
memcpy(buf + 32, pad256, 32);
/* compute and output hash */
ripemd160_rawcompress(buf, out);
}
8 changes: 8 additions & 0 deletions ripemd160_256.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef __RIPEMD160_256_H_
#define __RIPEMD160_256_H_

#include <stdint.h>

void ripemd160_256(const void *in, void *out);

#endif//__RIPEMD160_256_H_

0 comments on commit 2ab38f5

Please sign in to comment.