void Keychain::importBIP32(const secure_bytes_t& extkey, const secure_bytes_t& lock_key) { Coin::HDKeychain hdKeychain(extkey); depth_ = (uint32_t)hdKeychain.depth(); parent_fp_ = hdKeychain.parent_fp(); child_num_ = hdKeychain.child_num(); chain_code_ = hdKeychain.chain_code(); privkey_.clear(); if (hdKeychain.isPrivate()) { if (!lock_key.empty()) { privkey_salt_ = AES::random_salt(); privkey_ciphertext_ = AES::encrypt(lock_key, hdKeychain.key(), true, privkey_salt_); } else { privkey_salt_ = 0; privkey_ciphertext_ = hdKeychain.key(); } } else { privkey_salt_ = 0; privkey_ciphertext_.clear(); } pubkey_ = hdKeychain.pubkey(); hash_ = hdKeychain.full_hash(); }
bool Keychain::setPrivateKeyUnlockKey(const secure_bytes_t& lock_key, const bytes_t& /*salt*/) { if (!isPrivate()) throw std::runtime_error("Cannot lock the private key of a public keychain."); if (privkey_.empty()) throw std::runtime_error("Key is locked."); #ifdef ENABLE_CRYPTO if (lock_key.empty()) { privkey_ciphertext_ = privkey_; privkey_salt_.clear(); // empty salt means no encryption } else { // TODO: add real salt, better crypto function privkey_ciphertext_ = aes_encrypt(lock_key, privkey_, 0); privkey_salt_.clear(); privkey_salt_.push_back(1); } #else privkey_ciphertext_ = privkey_; privkey_salt_.clear(); #endif return true; }
Keychain::Keychain(const std::string& name, const secure_bytes_t& entropy, const secure_bytes_t& lock_key) : name_(name), hidden_(false) { if (name.empty() || name[0] == '@') throw std::runtime_error("Invalid keychain name."); if (entropy.size() < 16) throw std::runtime_error("At least 128 bits of entropy must be supplied."); Coin::HDSeed hdSeed(entropy); Coin::HDKeychain hdKeychain(hdSeed.getMasterKey(), hdSeed.getMasterChainCode()); depth_ = (uint32_t)hdKeychain.depth(); parent_fp_ = hdKeychain.parent_fp(); child_num_ = hdKeychain.child_num(); chain_code_ = hdKeychain.chain_code(); pubkey_ = hdKeychain.pubkey(); privkey_ = hdKeychain.privkey(); seed_ = entropy; if (lock_key.empty()) { privkey_salt_ = 0; privkey_ciphertext_ = privkey_; seed_salt_ = 0; seed_ciphertext_ = seed_; } else { privkey_salt_ = AES::random_salt(); privkey_ciphertext_ = AES::encrypt(lock_key, privkey_, true, privkey_salt_); seed_salt_ = AES::random_salt(); seed_ciphertext_ = AES::encrypt(lock_key, seed_, true, seed_salt_); } privkey_.clear(); seed_.clear(); hash_ = hdKeychain.full_hash(); }
bool Keychain::setChainCodeUnlockKey(const secure_bytes_t& lock_key, const bytes_t& /*salt*/) { if (chain_code_.empty()) throw std::runtime_error("Chain code is locked."); #ifdef ENABLE_CRYPTO if (lock_key.empty()) { chain_code_ciphertext_ = chain_code_; chain_code_salt_.clear(); } else { // TODO: add real salt, better crypto function chain_code_ciphertext_ = aes_encrypt(lock_key, chain_code_, 0); chain_code_salt_.clear(); chain_code_salt_.push_back(1); } #else chain_code_ciphertext_ = chain_code_; chain_code_salt_.clear(); #endif return true; }
std::shared_ptr<Keychain> Keychain::child(uint32_t i, bool get_private, const secure_bytes_t& lock_key) { if (get_private && !isPrivate()) throw std::runtime_error("Cannot get private child from nonprivate keychain."); if (get_private) { if (privkey_.empty()) throw std::runtime_error("Private key is locked."); Coin::HDKeychain hdkeychain(privkey_, chain_code_, child_num_, parent_fp_, depth_); hdkeychain = hdkeychain.getChild(i); std::shared_ptr<Keychain> child(new Keychain()); child->parent_ = get_shared_ptr(); child->pubkey_ = hdkeychain.pubkey(); child->chain_code_ = hdkeychain.chain_code(); child->privkey_ = hdkeychain.privkey(); if (lock_key.empty()) { child->privkey_salt_ = 0; child->privkey_ciphertext_ = privkey_; child->seed_salt_ = 0; child->seed_ciphertext_ = seed_; } else { child->privkey_salt_ = AES::random_salt(); child->privkey_ciphertext_ = AES::encrypt(lock_key, child->privkey_, true, child->privkey_salt_); if (seed_.empty()) { child->seed_salt_ = 0; } else { child->seed_salt_ = AES::random_salt(); child->seed_ciphertext_ = AES::encrypt(lock_key, seed_, true, child->seed_salt_); } } child->privkey_.clear(); child->child_num_ = hdkeychain.child_num(); child->parent_fp_ = hdkeychain.parent_fp(); child->depth_ = hdkeychain.depth(); child->hash_ = hdkeychain.full_hash(); child->derivation_path_ = derivation_path_; child->derivation_path_.push_back(i); return child; } else { Coin::HDKeychain hdkeychain(pubkey_, chain_code_, child_num_, parent_fp_, depth_); hdkeychain = hdkeychain.getChild(i); std::shared_ptr<Keychain> child(new Keychain());; child->parent_ = get_shared_ptr(); child->pubkey_ = hdkeychain.pubkey(); child->chain_code_ = hdkeychain.chain_code(); child->child_num_ = hdkeychain.child_num(); child->parent_fp_ = hdkeychain.parent_fp(); child->depth_ = hdkeychain.depth(); child->hash_ = hdkeychain.full_hash(); child->derivation_path_ = derivation_path_; child->derivation_path_.push_back(i); return child; } }