bool key_from_base58(secp256k1_context *secpctx, const char *base58, size_t base58_len, bool *test_net, struct privkey *priv, struct pubkey *key) { // 1 byte version, 32 byte private key, 1 byte compressed, 4 byte checksum u8 keybuf[1 + 32 + 1 + 4]; size_t keybuflen = sizeof(keybuf); b58tobin(keybuf, &keybuflen, base58, base58_len); if (b58check(keybuf, sizeof(keybuf), base58, base58_len) < 0) return false; /* Byte after key should be 1 to represent a compressed key. */ if (keybuf[1 + 32] != 1) return false; if (keybuf[0] == 128) *test_net = false; else if (keybuf[0] == 239) *test_net = true; else return false; /* Copy out secret. */ memcpy(priv->secret, keybuf + 1, sizeof(priv->secret)); if (!secp256k1_ec_seckey_verify(secpctx, priv->secret)) return false; /* Get public key, too. */ if (!pubkey_from_privkey(secpctx, priv, key)) return false; return true; }
static bool from_base58(u8 *version, struct ripemd160 *rmd, const char *base58, size_t base58_len) { u8 buf[1 + sizeof(*rmd) + 4]; b58_sha256_impl = my_sha256; size_t buflen = sizeof(buf); b58tobin(buf, &buflen, base58, base58_len); int r = b58check(buf, sizeof(buf), base58, base58_len); *version = buf[0]; memcpy(rmd, buf + 1, sizeof(*rmd)); return r > 0; }
int base58_decode_check(const char *str, uint8_t *data, int datalen) { if (datalen > 128) { return 0; } uint8_t d[datalen + 4]; size_t res = datalen + 4; if (b58tobin(d, &res, str) != true) { return 0; } uint8_t *nd = d + datalen + 4 - res; if (b58check(nd, res, str) < 0) { return 0; } memcpy(data, nd, res - 4); return res - 4; }
int base58_decode_check(const char *str, uint8_t *data, int datalen) { int ret; if (datalen > 128) { return 0; } uint8_t d[datalen + 4]; size_t res = datalen + 4; if (b58tobin(d, &res, str) != true) { ret = 0; } else if (res != (size_t)datalen + 4) { ret = 0; } else if (b58check(d, res, str) < 0) { ret = 0; } else { memcpy(data, d, datalen); ret = datalen; } utils_zero(d, sizeof(d)); return ret; }
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; rv = sizeof(addrbin); if (!b58_sha256_impl) b58_sha256_impl = blkmk_sha256_impl; if (!b58tobin(addrbin, &rv, addr, b58sz)) return 0; addrver = b58check(addrbin, sizeof(addrbin), addr, b58sz); switch (addrver) { case 0: // Bitcoin pubkey hash case 111: // Testnet pubkey hash if (outsz < (rv = 25)) return rv; cout[ 0] = 0x76; // OP_DUP cout[ 1] = 0xa9; // OP_HASH160 cout[ 2] = 0x14; // push 20 bytes memcpy(&cout[3], &addrbin[1], 20); cout[23] = 0x88; // OP_EQUALVERIFY cout[24] = 0xac; // OP_CHECKSIG return rv; case 5: // Bitcoin script hash case 196: // Testnet script hash if (outsz < (rv = 23)) return rv; cout[ 0] = 0xa9; // OP_HASH160 cout[ 1] = 0x14; // push 20 bytes memcpy(&cout[2], &addrbin[1], 20); cout[22] = 0x87; // OP_EQUAL return rv; default: return 0; } }
int _blkmk_b58check(void *bin, size_t binsz, const char *base58str) { if (!b58_sha256_impl) b58_sha256_impl = blkmk_sha256_impl; return b58check(bin, binsz, base58str, 34); }