From 5ab4fdff16ef49d3e1cd4dba6d82d3aedd548dfb Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 29 Dec 2012 02:33:22 +0000 Subject: [PATCH] Bugfix: _blkmk_b58check: Check that zero-padding on base58check input matches output This is needed to properly reject addresses with too many or too few prefix/pad '1's. --- base58.c | 12 ++++++++++-- example.c | 12 ++++++++++-- private.h | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/base58.c b/base58.c index 4a73849..3809804 100644 --- a/base58.c +++ b/base58.c @@ -83,13 +83,21 @@ bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz) { return true; } -int _blkmk_b58check(void *bin, size_t binsz) { +int _blkmk_b58check(void *bin, size_t binsz, const char *base58str) { unsigned char buf[32]; unsigned char *binc = bin; + unsigned i; 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]; } @@ -101,7 +109,7 @@ size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) { if (!_blkmk_b58tobin(addrbin, sizeof(addrbin), addr, 0)) return 0; - addrver = _blkmk_b58check(addrbin, sizeof(addrbin)); + addrver = _blkmk_b58check(addrbin, sizeof(addrbin), addr); switch (addrver) { case 0: // Bitcoin pubkey hash case 111: // Testnet pubkey hash diff --git a/example.c b/example.c index 5d68e6f..5382b91 100644 --- a/example.c +++ b/example.c @@ -13,16 +13,24 @@ #include "testinput.c" void testb58() { + int rv; + const char *iaddr = "11Baf75Ferj6A7AoN565gCQj9kGWbDMHfN9"; + const char *addr = &iaddr[1]; char bufx[26] = {'\xff'}; char *buf = &bufx[1]; - if (!_blkmk_b58tobin(buf, 25, "1Baf75Ferj6A7AoN565gCQj9kGWbDMHfN9", 0)) + if (!_blkmk_b58tobin(buf, 25, addr, 0)) exit(1); if (bufx[0] != '\xff') exit(2); char cbuf[51]; _blkmk_bin2hex(cbuf, buf, 25); printf("Base58 raw data: %s\n", cbuf); - printf("Base58 check: %d\n", _blkmk_b58check(buf, 25)); + assert((rv = _blkmk_b58check(buf, 25, addr)) == 0); + printf("Base58 check: %d\n", rv); + assert((rv = _blkmk_b58check(buf, 25, &addr[1])) < 0); + printf("Base58 check (invalid/ unpadded): %d\n", rv); + assert((rv = _blkmk_b58check(buf, 25, iaddr)) < 0); + printf("Base58 check (invalid/extra padded): %d\n", rv); } static diff --git a/private.h b/private.h index d23b831..02a298b 100644 --- a/private.h +++ b/private.h @@ -13,6 +13,6 @@ 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); +extern int _blkmk_b58check(void *bin, size_t binsz, const char *b58); #endif