Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/money-tree/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ def derive_private_key(i = 0)
return child_private_key, child_chain_code
end

def derive_parent_node(parent_key)
message = parent_key.public_key.to_bytes << i_as_bytes(index)
hash = hmac_sha512 hex_to_bytes(parent_key.chain_code_hex), message
priv = (private_key.to_i - left_from_hash(hash)) % MoneyTree::Key::ORDER
MoneyTree::Node.new(depth: parent_key.depth,
index: parent_key.index,
private_key: MoneyTree::PrivateKey.new(key: priv),
public_key: parent_key.public_key,
chain_code: parent_key.chain_code)
end

def derive_public_key(i = 0)
raise PrivatePublicMismatch if i >= PRIVATE_RANGE_LIMIT
message = public_derivation_message(i)
Expand Down
29 changes: 29 additions & 0 deletions spec/money-tree/node_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1311,5 +1311,34 @@
end
end
end

describe "deriving a parent node" do
before do
@master = MoneyTree::Master.new seed_hex: "000102030405060708090a0b0c0d0e0f"
@node = @master.node_for_path("m/101p")
@subnode = @node.node_for_path("1")
end
context "m/101'/1 -> m/101'" do
it "correctly derives from a subnode with priv key to a node knowing it's public key" do
node_priv_hex = @node.private_key.to_hex
@node.strip_private_info!
expect(@subnode.derive_parent_node(@node).private_key.to_hex).to eq(node_priv_hex)
end
end
context "m/101' -> master" do
it "unable to derive from a hardened node with priv key to a master node knowing it's public key" do
master_priv_hex = @master.private_key.to_hex
@master.strip_private_info!
expect(@node.derive_parent_node(@master).private_key.to_hex).to_not eq(master_priv_hex)
end
end
context "m/101 -> master" do
it "correctly derives from a non-hardened node with priv key to a master node knowing it's public key" do
@node = @master.node_for_path("m/101")
master_priv_hex = @master.private_key.to_hex
expect(@node.derive_parent_node(@master).private_key.to_hex).to eq(master_priv_hex)
end
end
end
end
end