bool bitcoin_from_base58(bool *test_net, struct bitcoin_address *addr, const char *base58, size_t base58_len) { u8 buf[1 + sizeof(addr->addr) + 4]; BIGNUM bn; size_t len; u8 csum[4]; BN_init(&bn); if (!raw_decode_base58(&bn, base58, base58_len)) return false; len = BN_num_bytes(&bn); if (len > sizeof(buf)) return false; memset(buf, 0, sizeof(buf)); BN_bn2bin(&bn, buf + sizeof(buf) - len); BN_free(&bn); if (buf[0] == 111) *test_net = true; else if (buf[0] == 0) *test_net = false; else return false; base58_get_checksum(csum, buf, 1 + sizeof(addr->addr)); if (memcmp(csum, buf + 1 + sizeof(addr->addr), sizeof(csum)) != 0) return false; memcpy(&addr->addr, buf+1, sizeof(addr->addr)); return true; }
static bool from_base58(u8 *version, struct ripemd160 *rmd, const char *base58, size_t base58_len) { u8 buf[1 + sizeof(*rmd) + 4]; BIGNUM bn; size_t len; u8 csum[4]; BN_init(&bn); if (!raw_decode_base58(&bn, base58, base58_len)) return false; len = BN_num_bytes(&bn); if (len > sizeof(buf)) return false; memset(buf, 0, sizeof(buf)); BN_bn2bin(&bn, buf + sizeof(buf) - len); BN_free(&bn); *version = buf[0]; base58_get_checksum(csum, buf, 1 + sizeof(*rmd)); if (memcmp(csum, buf + 1 + sizeof(*rmd), sizeof(csum)) != 0) return false; memcpy(rmd, buf+1, sizeof(*rmd)); return true; }
bool key_from_base58(secp256k1_context *secpctx, const char *base58, size_t base58_len, bool *test_net, struct privkey *priv, struct pubkey *key) { u8 keybuf[1 + 32 + 1 + 4]; u8 csum[4]; BIGNUM bn; bool compressed; size_t keylen; BN_init(&bn); if (!raw_decode_base58(&bn, base58, base58_len)) return false; keylen = BN_num_bytes(&bn); if (keylen == 1 + 32 + 4) compressed = false; else if (keylen == 1 + 32 + 1 + 4) compressed = true; else goto fail_free_bn; BN_bn2bin(&bn, keybuf); base58_get_checksum(csum, keybuf, keylen - sizeof(csum)); if (memcmp(csum, keybuf + keylen - sizeof(csum), sizeof(csum)) != 0) goto fail_free_bn; /* Byte after key should be 1 to represent a compressed key. */ if (compressed && keybuf[1 + 32] != 1) goto fail_free_bn; if (keybuf[0] == 128) *test_net = false; else if (keybuf[0] == 239) *test_net = true; else goto fail_free_bn; /* Copy out secret. */ memcpy(priv->secret, keybuf + 1, sizeof(priv->secret)); if (!secp256k1_ec_seckey_verify(secpctx, priv->secret)) goto fail_free_bn; /* Get public key, too, since we know if it's compressed. */ if (!pubkey_from_privkey(secpctx, priv, key, compressed ? SECP256K1_EC_COMPRESSED : 0)) goto fail_free_bn; BN_free(&bn); return true; fail_free_bn: BN_free(&bn); return false; }
bool ripemd_from_base58(u8 *version, struct ripemd160 *ripemd160, const char *base58) { u8 buf[1 + sizeof(*ripemd160) + 4]; u8 csum[4]; BIGNUM bn; size_t len; /* Too long? Check here before doing arithmetic. */ 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; /* Too big? */ len = BN_num_bytes(&bn); if (len > sizeof(buf)) { BN_free(&bn); return false; } /* Fill start with zeroes. */ memset(buf, 0, sizeof(buf) - len); BN_bn2bin(&bn, buf + sizeof(buf) - len); BN_free(&bn); /* Check checksum is correct. */ base58_get_checksum(csum, buf, sizeof(buf)); if (memcmp(csum, buf + 1 + sizeof(*ripemd160), 4) != 0) return false; *version = buf[0]; memcpy(ripemd160, buf + 1, sizeof(*ripemd160)); return true; }
bool key_from_base58(const char *base58, size_t base58_len, bool *test_net, struct privkey *priv, struct pubkey *key) { u8 keybuf[1 + 32 + 1 + 4]; u8 csum[4]; BIGNUM bn; bool compressed; secp256k1_context_t *secpctx; int keylen; BN_init(&bn); if (!raw_decode_base58(&bn, base58, base58_len)) return false; keylen = BN_num_bytes(&bn); if (keylen == 1 + 32 + 4) compressed = false; else if (keylen == 1 + 32 + 1 + 4) compressed = true; else goto fail_free_bn; BN_bn2bin(&bn, keybuf); base58_get_checksum(csum, keybuf, keylen - sizeof(csum)); if (memcmp(csum, keybuf + keylen - sizeof(csum), sizeof(csum)) != 0) goto fail_free_bn; /* Byte after key should be 1 to represent a compressed key. */ if (compressed && keybuf[1 + 32] != 1) goto fail_free_bn; if (keybuf[0] == 128) *test_net = false; else if (keybuf[0] == 239) *test_net = true; else goto fail_free_bn; /* Copy out secret. */ memcpy(priv->secret, keybuf + 1, sizeof(priv->secret)); secpctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); if (!secp256k1_ec_seckey_verify(secpctx, priv->secret)) goto fail_free_secpctx; /* Get public key, too. */ if (!secp256k1_ec_pubkey_create(secpctx, key->key, &keylen, priv->secret, compressed)) goto fail_free_secpctx; assert(keylen == pubkey_len(key)); BN_free(&bn); secp256k1_context_destroy(secpctx); return true; fail_free_secpctx: secp256k1_context_destroy(secpctx); fail_free_bn: BN_free(&bn); return false; }