Use libbase58 for base58 decoding
This commit is contained in:
parent
4b87cfeeaa
commit
d46062c7e6
@ -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 = \
|
||||
|
||||
90
base58.c
90
base58.c
@ -15,6 +15,8 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libbase58.h>
|
||||
|
||||
#include <blkmaker.h>
|
||||
|
||||
#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
|
||||
|
||||
@ -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
|
||||
|
||||
12
example.c
12
example.c
@ -12,6 +12,7 @@
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include <libbase58.h>
|
||||
|
||||
#include <blkmaker.h>
|
||||
#include <blkmaker_jansson.h>
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user