Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rustyrussell/pettycoin
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 964043b4be84
Choose a base ref
...
head repository: rustyrussell/pettycoin
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 10e7c7705003
Choose a head ref
  • 3 commits
  • 4 files changed
  • 1 contributor

Commits on Aug 15, 2014

  1. caller_do_bn_init.patch

    Problem:
    
    raw_decode_base_n leaks if we allocate the bignum with BN_new(),
    because BN_init() is called on an initialized BIGNUM.
    
    Fix:
    
    raw_decode_base58 no longer calls BN_init() and the caller has to call
    BN_init() if needed.
    
    Signed-off-by: Nelson Castillo <nelsoneci@gmail.com>
    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    arhuaco authored and rustyrussell committed Aug 15, 2014
    Copy the full SHA
    243822f View commit details
  2. Add function raw_decode_base_n

    Generalize raw_decode_base58 and make raw_decode_base58 depend on
    raw_decode_base_n.
    
    This will make it decoding from other bases easier in the future.
    
    Signed-off-by: Nelson Castillo <nelsoneci@gmail.com>
    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    arhuaco authored and rustyrussell committed Aug 15, 2014
    Copy the full SHA
    783aa38 View commit details
  3. Add a test for raw_decode_base_n with n=16

    This is the first time that we test raw_decode_base_* with a BIGNUM that
    is allocated with BN_new. This function was leaking before and it doesn not
    leak now that raw_decode_base_n does not call BN_init (Fixed in previous patch).
    
    In other workds, this call sequence works well now:
    
      bn_priv = BN_new();
      assert(raw_decode_base_n(bn_priv, priv_b16, strlen(priv_b16), 16));
    
    Signed-off-by: Nelson Castillo <nelsoneci@gmail.com>
    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    arhuaco authored and rustyrussell committed Aug 15, 2014
    Copy the full SHA
    10e7c77 View commit details
Showing with 71 additions and 15 deletions.
  1. +37 −10 base58.c
  2. +1 −0 base58.h
  3. +28 −0 test/run-01-base16.c
  4. +5 −5 test/run-01-base58.c
47 changes: 37 additions & 10 deletions base58.c
Original file line number Diff line number Diff line change
@@ -12,16 +12,17 @@
#include <openssl/sha.h>
#include <string.h>

static const char enc[] =
static const char enc_16[] = "0123456789abcdef";
static const char enc_58[] =
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

static char encode_char(unsigned long val)
static char encode_char(unsigned long val, const char *enc)
{
assert(val < strlen(enc));
return enc[val];
}

static int decode_char(char c)
static int decode_char(char c, const char *enc)
{
const char *pos = strchr(enc, c);
if (!pos)
@@ -58,7 +59,7 @@ static char *encode_base58(char *buf, size_t buflen,
p = NULL;
goto out;
}
*p = encode_char(rem);
*p = encode_char(rem, enc_58);
}

/* Now, this is really weird. We pad with zeroes, but not at
@@ -69,7 +70,7 @@ static char *encode_base58(char *buf, size_t buflen,
p = NULL;
goto out;
}
*p = encode_char(0);
*p = encode_char(0, enc_58);
data_len--;
data++;
}
@@ -80,20 +81,35 @@ static char *encode_base58(char *buf, size_t buflen,
}

/*
* Decode a base58-encoded string into a byte sequence.
* Decode a base_n-encoded string into a byte sequence.
*/
bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len)
bool raw_decode_base_n(BIGNUM *bn, const char *src, size_t len, int base)
{
BN_init(bn);
const char *enc;

BN_zero(bn);

assert(base == 16 || base == 58);
switch (base) {
case 16:
enc = enc_16;
break;
case 58:
enc = enc_58;
break;
}

while (len) {
int val = decode_char(*src);
char current = *src;

if (base == 16)
current = tolower(current); /* TODO: Not in ccan. */
int val = decode_char(current, enc);
if (val < 0) {
BN_free(bn);
return false;
}
BN_mul_word(bn, 58);
BN_mul_word(bn, base);
BN_add_word(bn, val);
src++;
len--;
@@ -102,6 +118,14 @@ bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len)
return true;
}

/*
* Decode a base58-encoded string into a byte sequence.
*/
bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len)
{
return raw_decode_base_n(bn, src, len, 58);
}

void base58_get_checksum(u8 csum[4], const u8 buf[], size_t buflen)
{
SHA256_CTX sha256;
@@ -163,6 +187,7 @@ bool pettycoin_from_base58(bool *test_net,
base58_len -= 2;
}

BN_init(&bn);
if (!raw_decode_base58(&bn, base58, base58_len))
return false;

@@ -224,6 +249,7 @@ bool ripemd_from_base58(u8 *version, u8 ripemd160[RIPEMD160_DIGEST_LENGTH],
if (strlen(base58) > BASE58_ADDR_MAX_LEN - 1)
return false;

BN_init(&bn);
/* Fails if it contains invalid characters. */
if (!raw_decode_base58(&bn, base58, strlen(base58)))
return false;
@@ -329,6 +355,7 @@ EC_KEY *key_from_base58(const char *base58, size_t base58_len,
} else
is_bitcoin = false;

BN_init(&bn);
if (!raw_decode_base58(&bn, base58, base58_len))
return NULL;

1 change: 1 addition & 0 deletions base58.h
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ char *key_to_base58(const tal_t *ctx, bool test_net, EC_KEY *key,
EC_KEY *key_from_base58(const char *base58, size_t base58_len,
bool *test_net, struct protocol_pubkey *key);

bool raw_decode_base_n(BIGNUM *bn, const char *src, size_t len, int base);
bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len);
void base58_get_checksum(u8 csum[4], const u8 buf[], size_t buflen);

28 changes: 28 additions & 0 deletions test/run-01-base16.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "../base58.c"

int main(void)
{
/* Address: 1PtcjakvZBeggokcAGb1KbVvMRi3NT6LMk. */
const char priv_b16[] =
"4e111544df178877C7e8483e92b7ef1b40cE7dc4e944261f4f32e2ed13340c0A";
const char priv_b10[] =
"35310585383039988783548932038956396952442822145226977502125905800903068486666";

BIGNUM *bn_priv;
BIGNUM *bn_priv_from_dec = NULL;
BIGNUM *bn_priv_from_hex = NULL;

bn_priv = BN_new();
assert(raw_decode_base_n(bn_priv, priv_b16, strlen(priv_b16), 16));
assert(BN_dec2bn(&bn_priv_from_dec, priv_b10) == strlen(priv_b10));
assert(BN_hex2bn(&bn_priv_from_hex, priv_b16) == strlen(priv_b16));

assert(BN_cmp(bn_priv, bn_priv_from_dec) == 0);
assert(BN_cmp(bn_priv, bn_priv_from_hex) == 0);

BN_free(bn_priv_from_hex);
BN_free(bn_priv_from_dec);
BN_free(bn_priv);

return 0;
}
10 changes: 5 additions & 5 deletions test/run-01-base58.c
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ int main(void)
assert(tal_parent(p) == ctx);
assert(p[0] == 'P');
assert(strlen(p) < BASE58_ADDR_MAX_LEN);
assert(strspn(p, enc) == strlen(p));
assert(strspn(p, enc_58) == strlen(p));
memset(&addr2, 0, sizeof(addr2));
assert(pettycoin_from_base58(&test_net, &addr2, p, strlen(p)));
assert(test_net == false);
@@ -29,7 +29,7 @@ int main(void)
assert(tal_parent(p) == ctx);
assert(p[0] == 'q');
assert(strlen(p) < BASE58_ADDR_MAX_LEN);
assert(strspn(p, enc) == strlen(p));
assert(strspn(p, enc_58) == strlen(p));
memset(&addr2, 0, sizeof(addr2));
assert(pettycoin_from_base58(&test_net, &addr2, p, strlen(p)));
assert(test_net == true);
@@ -40,7 +40,7 @@ int main(void)
assert(tal_parent(p) == ctx);
assert(strstarts(p, "P-1"));
assert(strlen(p) < BASE58_ADDR_MAX_LEN + 2);
assert(strspn(p+2, enc) == strlen(p+2));
assert(strspn(p+2, enc_58) == strlen(p+2));
memset(&addr2, 0, sizeof(addr2));
assert(pettycoin_from_base58(&test_net, &addr2, p, strlen(p)));
assert(test_net == false);
@@ -51,7 +51,7 @@ int main(void)
assert(tal_parent(p) == ctx);
assert(strstarts(p, "P-m") || strstarts(p, "P-n"));
assert(strlen(p) < BASE58_ADDR_MAX_LEN + 2);
assert(strspn(p+2, enc) == strlen(p+2));
assert(strspn(p+2, enc_58) == strlen(p+2));
memset(&addr2, 0, sizeof(addr2));
assert(pettycoin_from_base58(&test_net, &addr2, p, strlen(p)));
assert(test_net == true);
@@ -75,7 +75,7 @@ int main(void)

/* Now, turn it into pettcoin-style key. */
p = key_to_base58(ctx, true, key, false);
assert(strspn(p, enc) == strlen(p));
assert(strspn(p, enc_58) == strlen(p));

/* Convert back, check it is OK. */
EC_KEY_free(key);