From d46062c7e66bd57e5e2640c4289c127c150bb495 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 22 Aug 2014 19:07:56 +0000 Subject: [PATCH] Use libbase58 for base58 decoding --- Makefile.am | 7 +++- base58.c | 90 +++++++--------------------------------------------- configure.ac | 2 ++ example.c | 12 ++++--- private.h | 4 --- 5 files changed, 28 insertions(+), 87 deletions(-) diff --git a/Makefile.am b/Makefile.am index c3b9a88..578acab 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,12 @@ libblkmaker_@LIBBLKMAKER_API_VERSION@_la_SOURCES = \ hex.c \ private.h -libblkmaker_@LIBBLKMAKER_API_VERSION@_la_LDFLAGS = -version-info $(LIBBLKMAKER_SO_VERSION) -no-undefined +libblkmaker_@LIBBLKMAKER_API_VERSION@_la_CFLAGS = \ + $(libbase58_CFLAGS) +libblkmaker_@LIBBLKMAKER_API_VERSION@_la_LDFLAGS = \ + $(libbase58_LIBS) \ + -no-undefined \ + -version-info $(LIBBLKMAKER_SO_VERSION) libblkmaker_includedir = $(includedir)/libblkmaker-$(LIBBLKMAKER_API_VERSION) libblkmaker_include_HEADERS = \ diff --git a/base58.c b/base58.c index 50daefc..8565dd5 100644 --- a/base58.c +++ b/base58.c @@ -15,6 +15,8 @@ #include #include +#include + #include #include "private.h" @@ -31,96 +33,28 @@ static const int8_t b58digits[] = { }; bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz) { - const unsigned char *b58u = (void*)b58; - unsigned char *binu = bin; - size_t outisz = (binsz + 3) / 4; - uint32_t outi[outisz]; - uint64_t t; - uint32_t c; - size_t i, j; - uint8_t bytesleft = binsz % 4; - uint32_t zeromask = ~((1 << ((bytesleft ?: 4) * 8)) - 1); - - if (!b58sz) - b58sz = strlen(b58); - - memset(outi, 0, outisz * sizeof(*outi)); - - for (i = 0; i < b58sz; ++i) - { - if (b58u[i] & 0x80) - // High-bit set on invalid digit - return false; - if (b58digits[b58u[i]] == -1) - // Invalid base58 digit - return false; - c = b58digits[b58u[i]]; - for (j = outisz; j--; ) - { - t = ((uint64_t)outi[j]) * 58 + c; - c = (t & 0x3f00000000) >> 32; - outi[j] = t & 0xffffffff; - } - if (c) - // Output number too big (carry to the next int32) - return false; - if (outi[0] & zeromask) - // Output number too big (last int32 filled too far) - return false; - } - - j = 0; - switch (bytesleft) { - case 3: - *(binu++) = (outi[0] & 0xff0000) >> 16; - case 2: - *(binu++) = (outi[0] & 0xff00) >> 8; - case 1: - *(binu++) = (outi[0] & 0xff); - ++j; - default: - break; - } - - for (; j < outisz; ++j) - { - *(binu++) = outi[j] >> 0x18; - *(binu++) = outi[j] >> 0x10; - *(binu++) = outi[j] >> 8; - *(binu++) = outi[j]; - } - return true; + return b58tobin(bin, &binsz, b58, b58sz); } int _blkmk_b58check(void *bin, size_t binsz, const char *base58str) { - unsigned char buf[32]; - unsigned char *binc = bin; - unsigned i; - if (binsz < 4) - return -4; - if (!_blkmk_dblsha256(buf, bin, binsz - 4)) - return -2; - if (memcmp(&binc[binsz - 4], buf, 4)) - return -1; - - // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) - for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) - {} // Just finding the end of zeros, nothing to do in loop - if (binc[i] == '\0' || base58str[i] == '1') - return -3; - - return binc[0]; + if (!b58_sha256_impl) + b58_sha256_impl = blkmk_sha256_impl; + return b58check(bin, binsz, base58str, 34); } size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) { unsigned char addrbin[25]; unsigned char *cout = out; + const size_t b58sz = strlen(addr); int addrver; size_t rv; - if (!_blkmk_b58tobin(addrbin, sizeof(addrbin), addr, 0)) + rv = sizeof(addrbin); + if (!b58_sha256_impl) + b58_sha256_impl = blkmk_sha256_impl; + if (!b58tobin(addrbin, &rv, addr, b58sz)) return 0; - addrver = _blkmk_b58check(addrbin, sizeof(addrbin), addr); + addrver = b58check(addrbin, sizeof(addrbin), addr, b58sz); switch (addrver) { case 0: // Bitcoin pubkey hash case 111: // Testnet pubkey hash diff --git a/configure.ac b/configure.ac index ed4ea00..c455bd8 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,8 @@ PKG_CHECK_MODULES([JANSSON],[jansson],[ AC_SUBST(JANSSON_CFLAGS) AC_SUBST(JANSSON_LIBS) +PKG_CHECK_MODULES([libbase58],[libbase58]) + AC_CHECK_LIB([ws2_32], [strchr]) AC_OUTPUT diff --git a/example.c b/example.c index 7f8c1e2..b6306de 100644 --- a/example.c +++ b/example.c @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -23,20 +24,23 @@ void testb58() { int rv; const char *iaddr = "11Baf75Ferj6A7AoN565gCQj9kGWbDMHfN9"; const char *addr = &iaddr[1]; + const size_t addrlen = strlen(addr); + size_t actuallen; char bufx[26] = {'\xff'}; char *buf = &bufx[1]; - if (!_blkmk_b58tobin(buf, 25, addr, 0)) + actuallen = 25; + if (!b58tobin(buf, &actuallen, addr, addrlen)) exit(1); if (bufx[0] != '\xff') exit(2); char cbuf[51]; _blkmk_bin2hex(cbuf, buf, 25); printf("Base58 raw data: %s\n", cbuf); - assert((rv = _blkmk_b58check(buf, 25, addr)) == 0); + assert((rv = b58check(buf, 25, addr, addrlen)) == 0); printf("Base58 check: %d\n", rv); - assert((rv = _blkmk_b58check(buf, 25, &addr[1])) < 0); + assert((rv = b58check(buf, 25, &addr[1], addrlen)) < 0); printf("Base58 check (invalid/ unpadded): %d\n", rv); - assert((rv = _blkmk_b58check(buf, 25, iaddr)) < 0); + assert((rv = b58check(buf, 25, iaddr, addrlen + 1)) < 0); printf("Base58 check (invalid/extra padded): %d\n", rv); } diff --git a/private.h b/private.h index f0e437a..4963898 100644 --- a/private.h +++ b/private.h @@ -14,10 +14,6 @@ extern void _blktxn_free(struct blktxn_t *); extern void _blkmk_bin2hex(char *out, const void *data, size_t datasz); extern bool _blkmk_hex2bin(void *o, const char *x, size_t len); -// base58.c -extern bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz); -extern int _blkmk_b58check(void *bin, size_t binsz, const char *b58); - // inline // NOTE: This must return 0 for 0