static bool check_keys_match(const struct hd_extended_key *ekA, const struct hd_extended_key *ekB) { void *pubkeyA; size_t pubkeyA_len; void *pubkeyB; size_t pubkeyB_len; bool result = false; if (bp_pubkey_get(&ekA->key, &pubkeyA, &pubkeyA_len)) { if (bp_pubkey_get(&ekB->key, &pubkeyB, &pubkeyB_len)) { result = (pubkeyB_len == pubkeyA_len) && (0 == memcmp(pubkeyA, pubkeyB, pubkeyA_len)); free(pubkeyB); } free(pubkeyA); } return result; }
static void load_json_key(json_t *wallet, struct bp_key *key) { json_t *keys_a = json_object_get(wallet, "keys"); assert(json_is_array(keys_a)); json_t *key_o = json_array_get(keys_a, 0); assert(json_is_object(key_o)); const char *address_str = json_string_value(json_object_get(key_o, "address")); assert(address_str != NULL); const char *privkey_address_str = json_string_value(json_object_get(key_o, "privkey_address")); assert(privkey_address_str); const char *pubkey_str = json_string_value(json_object_get(key_o, "pubkey")); assert(pubkey_str != NULL); const char *privkey_str = json_string_value(json_object_get(key_o, "privkey")); assert(privkey_str != NULL); char rawbuf[strlen(privkey_str)]; size_t buf_len = 0; /* decode privkey */ assert(decode_hex(rawbuf, sizeof(rawbuf), privkey_str, &buf_len) == true); assert(bp_privkey_set(key, rawbuf, buf_len) == true); /* decode pubkey */ assert(decode_hex(rawbuf, sizeof(rawbuf), pubkey_str, &buf_len) == true); void *pk = NULL; size_t pk_len = 0; /* verify pubkey matches expected */ assert(bp_pubkey_get(key, &pk, &pk_len) == true); assert(pk_len == buf_len); assert(memcmp(rawbuf, pk, pk_len) == 0); free(pk); /* verify pubkey hash (bitcoin address) matches expected */ cstring *btc_addr = bp_pubkey_get_address(key, PUBKEY_ADDRESS_TEST); assert(strlen(address_str) == btc_addr->len); assert(memcmp(address_str, btc_addr->str, btc_addr->len) == 0); /* verify the private key address (WIF) */ cstring *privkey_addr = bp_privkey_get_address(key, PRIVKEY_ADDRESS_TEST); assert(strlen(privkey_address_str) == privkey_addr->len); assert(memcmp(privkey_address_str, privkey_addr->str, privkey_addr->len) == 0); cstr_free(privkey_addr, true); cstr_free(btc_addr, true); }
static void print_ek_public(const struct hd_extended_key *ek) { printf(" version : 0x%08x\n", ek->version); printf(" depth : %d\n", ek->depth); printf(" parent : 0x"); print_n(ek->parent_fingerprint, 4); NEWLINE; printf(" index : %d\n", ek->index); printf(" chaincode : "); print_n(ek->chaincode.data, 32); NEWLINE; void *pub; size_t pub_len = 0; bp_pubkey_get(&ek->key, &pub, &pub_len); printf(" pub key : "); print_n(pub, pub_len); NEWLINE; free(pub); }
bool bkeys_add(struct bp_keystore *ks, struct bp_key *key) { bu160_t *hash; void *pubkey = NULL; size_t pk_len = 0; if (!bp_pubkey_get(key, &pubkey, &pk_len)) return false; hash = malloc(sizeof(*hash)); bu_Hash160((unsigned char *)hash, pubkey, pk_len); free(pubkey); g_hash_table_insert(ks->keys, hash, key); return true; }
static void keytest() { { struct bp_key k; bp_key_init(&k); bp_key_free(&k); } // Signature { const uint8_t test_secret[32] = { 0x1 }; const uint8_t test_data[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; bu256_t hash; SHA256(test_data, sizeof(test_data), (uint8_t *)&hash); void *pub = NULL; size_t publen = 0; void *sig = NULL; size_t siglen = 0; struct bp_key k; bp_key_init(&k); assert(bp_key_secret_set(&k, test_secret, sizeof(test_secret))); assert(bp_pubkey_get(&k, &pub, &publen)); assert(NULL != pub); assert(0 != publen); assert(bp_sign(&k, (uint8_t *)&hash, sizeof(hash), &sig, &siglen)); assert(NULL != sig); assert(0 != siglen); bp_key_free(&k); struct bp_key pubk; bp_key_init(&k); assert(bp_pubkey_set(&pubk, pub, publen)); assert(bp_verify(&pubk, (uint8_t *)&hash, sizeof(hash), sig, siglen)); bp_key_free(&k); free(pub); free(sig); } }
bool bpks_add(struct bp_keyset *ks, struct bp_key *key) { void *pubkey = NULL; size_t pk_len = 0; if (!bp_pubkey_get(key, &pubkey, &pk_len)) return false; struct buffer *buf_pk = malloc(sizeof(struct buffer)); buf_pk->p = pubkey; buf_pk->len = pk_len; unsigned char md160[RIPEMD160_DIGEST_LENGTH]; bu_Hash160(md160, pubkey, pk_len); struct buffer *buf_pkhash = buffer_copy(md160, RIPEMD160_DIGEST_LENGTH); g_hash_table_replace(ks->pub, buf_pk, buf_pk); g_hash_table_replace(ks->pubhash, buf_pkhash, buf_pkhash); return true; }
bool bkeys_pubkey_append(struct bp_keystore *ks, const bu160_t *key_id, GString *scriptSig) { struct bp_key key; bp_key_init(&key); if (!bkeys_key_get(ks, key_id, &key)) return false; void *pubkey = NULL; size_t pk_len = 0; if (!bp_pubkey_get(&key, &pubkey, &pk_len)) return false; bsp_push_data(scriptSig, pubkey, pk_len); free(pubkey); /* no bp_key_free(&key), as bkeys_key_get() returns a ref */ return true; }
std::vector<unsigned char> decrypt_bip38_ec(const std::vector<unsigned char> key, const std::string& passwd) { int i; uint8_t passfactor[PASSFACTOR_SIZE]; memset(passfactor,0,PASSFACTOR_SIZE); const unsigned char * s_key = reinterpret_cast<const unsigned char*>(key.data()); crypto_scrypt((const uint8_t *)passwd.c_str(), passwd.length(), &s_key[3 + ADDRESSHASH_SIZE], OWNERSALT_SIZE, 16384, 8, 8, passfactor, PASSFACTOR_SIZE ); // compute EC point (passpoint) using passfactor struct bp_key ec_point; if(!bp_key_init(&ec_point)) { fprintf(stderr,"%s","cannot init EC point key"); exit(3); } if(!bp_key_secret_set(&ec_point,passfactor,PASSFACTOR_SIZE)) { fprintf(stderr,"%s","cannot set EC point from passfactor"); exit(3); } // get the passpoint as bytes unsigned char * passpoint; size_t passpoint_len; if(!bp_pubkey_get(&ec_point,(unsigned char **)&passpoint,&passpoint_len)) { fprintf(stderr,"%s","cannot get pubkey for EC point"); exit(4); } // now we need to decrypt seedb uint8_t encryptedpart2[16]; memset(encryptedpart2,0,16); memcpy(encryptedpart2, &s_key[3 + ADDRESSHASH_SIZE + OWNERSALT_SIZE + 8], 16); uint8_t encryptedpart1[16]; memset(encryptedpart1,0,16); memcpy(encryptedpart1, &s_key[3 + ADDRESSHASH_SIZE + OWNERSALT_SIZE], 8); unsigned char derived[DERIVED_SIZE]; // get the encryption key for seedb using scrypt // with passpoint as the key, salt is addresshash+ownersalt unsigned char derived_scrypt_salt[ADDRESSHASH_SIZE + OWNERSALT_SIZE]; memcpy(derived_scrypt_salt, &s_key[3], ADDRESSHASH_SIZE); // copy the addresshash memcpy(derived_scrypt_salt+ADDRESSHASH_SIZE, &s_key[3+ADDRESSHASH_SIZE], OWNERSALT_SIZE); // copy the ownersalt crypto_scrypt( passpoint, passpoint_len, derived_scrypt_salt, ADDRESSHASH_SIZE+OWNERSALT_SIZE, 1024, 1, 1, derived, DERIVED_SIZE ); //get decryption key unsigned char derivedhalf2[DERIVED_SIZE/2]; memcpy(derivedhalf2, derived+(DERIVED_SIZE/2), DERIVED_SIZE/2); unsigned char iv[32]; memset(iv,0,32); EVP_CIPHER_CTX d; EVP_CIPHER_CTX_init(&d); EVP_DecryptInit_ex(&d, EVP_aes_256_ecb(), NULL, derivedhalf2, iv); unsigned char unencryptedpart2[32]; int decrypt_len; EVP_DecryptUpdate(&d, unencryptedpart2, &decrypt_len, encryptedpart2, 16); EVP_DecryptUpdate(&d, unencryptedpart2, &decrypt_len, encryptedpart2, 16); for(i=0; i<16; i++) { unencryptedpart2[i] ^= derived[i + 16]; } unsigned char unencryptedpart1[32]; memcpy(encryptedpart1+8, unencryptedpart2, 8); EVP_DecryptUpdate(&d, unencryptedpart1, &decrypt_len, encryptedpart1, 16); EVP_DecryptUpdate(&d, unencryptedpart1, &decrypt_len, encryptedpart1, 16); for(i=0; i<16; i++) { unencryptedpart1[i] ^= derived[i]; } // recoved seedb unsigned char seedb[24]; memcpy(seedb, unencryptedpart1, 16); memcpy(&(seedb[16]), &(unencryptedpart2[8]), 8); // turn seedb into factorb (factorb = SHA256(SHA256(seedb))) unsigned char factorb[32]; bu_Hash(factorb, seedb, 24); // multiply by passfactor (ec_point_pub) const EC_GROUP * ec_group = EC_KEY_get0_group(ec_point.k); const EC_POINT * ec_point_pub = EC_KEY_get0_public_key(ec_point.k); BIGNUM * bn_passfactor = BN_bin2bn(passfactor,32,BN_new()); BIGNUM * bn_factorb = BN_bin2bn(factorb,32,BN_new()); BIGNUM * bn_res = BN_new(); BIGNUM * bn_final = BN_new(); BIGNUM * bn_n = BN_new(); BN_CTX * ctx = BN_CTX_new(); EC_GROUP_get_order(ec_group, bn_n, ctx); BN_mul(bn_res, bn_passfactor, bn_factorb, ctx); BN_mod(bn_final, bn_res, bn_n, ctx); unsigned char finalKey[32]; memset(finalKey, 0, 32); int n = BN_bn2bin(bn_final, finalKey); BN_clear_free(bn_passfactor); BN_clear_free(bn_factorb); BN_clear_free(bn_res); BN_clear_free(bn_n); BN_clear_free(bn_final); printf("\n"); print_hex((char *)finalKey, 32); printf("\n"); std::vector<unsigned char> out; out.assign(finalKey, finalKey + 32); return out; }
static void runtest(void) { unsigned int i; struct bp_key keys[4]; /* generate keys */ for (i = 0; i < ARRAY_SIZE(keys); i++) { struct bp_key *key = &keys[i]; assert(bp_key_init(key) == true); assert(bp_key_generate(key) == true); } struct bp_keyset ks; bpks_init(&ks); /* add all but one to keyset */ for (i = 0; i < (ARRAY_SIZE(keys) - 1); i++) assert(bpks_add(&ks, &keys[i]) == true); /* verify all-but-one are in keyset */ for (i = 0; i < (ARRAY_SIZE(keys) - 1); i++) { unsigned char md160[RIPEMD160_DIGEST_LENGTH]; void *pubkey; size_t pklen; assert(bp_pubkey_get(&keys[i], &pubkey, &pklen) == true); bu_Hash160(md160, pubkey, pklen); assert(bpks_lookup(&ks, pubkey, pklen, true) == false); assert(bpks_lookup(&ks, pubkey, pklen, false) == true); assert(bpks_lookup(&ks, md160, sizeof(md160), true) == true); assert(bpks_lookup(&ks, md160, sizeof(md160), false) == false); free(pubkey); } /* verify last key not in keyset */ { unsigned char md160[RIPEMD160_DIGEST_LENGTH]; void *pubkey; size_t pklen; struct bp_key *key = &keys[ARRAY_SIZE(keys) - 1]; assert(bp_pubkey_get(key, &pubkey, &pklen) == true); bu_Hash160(md160, pubkey, pklen); assert(bpks_lookup(&ks, pubkey, pklen, true) == false); assert(bpks_lookup(&ks, pubkey, pklen, false) == false); assert(bpks_lookup(&ks, md160, sizeof(md160), true) == false); assert(bpks_lookup(&ks, md160, sizeof(md160), false) == false); free(pubkey); } bpks_free(&ks); for (i = 0; i < ARRAY_SIZE(keys); i++) { struct bp_key *key = &keys[i]; bp_key_free(key); } }