Skip to content

Commit b737dff

Browse files
authored
feat: derive Keystore public key from secret key (#1067)
1 parent 5160683 commit b737dff

File tree

4 files changed

+43
-2
lines changed

4 files changed

+43
-2
lines changed

lib/bls.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ defmodule Bls do
5454
:erlang.nif_error(:nif_not_loaded)
5555
end
5656

57+
@spec derive_pubkey(privkey()) :: {:ok, pubkey()} | {:error, any()}
58+
def derive_pubkey(_private_key) do
59+
:erlang.nif_error(:nif_not_loaded)
60+
end
61+
5762
##### Helpers #####
5863
@doc """
5964
Same as ``Bls.verify``, but treats errors as invalid signatures.

lib/keystore.ex

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,15 @@ defmodule Keystore do
2323
validate_empty_path!(decoded_json["path"])
2424

2525
privkey = decrypt!(decoded_json["crypto"], password)
26-
# TODO: derive from privkey and validate with this pubkey
26+
2727
pubkey = Map.fetch!(decoded_json, "pubkey") |> parse_binary!()
28+
29+
{:ok, derived_pubkey} = Bls.derive_pubkey(privkey)
30+
31+
if derived_pubkey != pubkey do
32+
raise("Keystore secret and public keys don't form a valid pair")
33+
end
34+
2835
{pubkey, privkey}
2936
end
3037

native/bls_nif/src/lib.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,17 @@ fn key_validate<'env>(public_key: Binary) -> Result<bool, String> {
161161

162162
Ok(true)
163163
}
164+
#[rustler::nif]
165+
fn derive_pubkey<'env>(env: Env<'env>, private_key: Binary) -> Result<Binary<'env>, String> {
166+
let sk = match SecretKey::deserialize(private_key.as_slice()) {
167+
Ok(sk) => sk,
168+
Err(e) => return Err(format!("{:?}", e)),
169+
};
170+
let public_key = sk.public_key();
171+
let public_key_bytes = public_key.serialize();
172+
173+
Ok(bytes_to_binary(env, &public_key_bytes))
174+
}
164175

165176
rustler::init!(
166177
"Elixir.Bls",
@@ -172,6 +183,7 @@ rustler::init!(
172183
eth_fast_aggregate_verify,
173184
eth_aggregate_pubkeys,
174185
verify,
175-
key_validate
186+
key_validate,
187+
derive_pubkey
176188
]
177189
);

test/unit/bls_test.exs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,21 @@ defmodule BlsTest do
1717
assert Bls.key_validate(invalid_public_key) == {:error, "BlstError(BLST_BAD_ENCODING)"}
1818
end
1919
end
20+
21+
describe "Private to public key" do
22+
test "return the correct public key for a private key" do
23+
valid_public_key =
24+
Base.decode16!(
25+
"8abb15ca57942b6225af4710bbb74ce8466e99fdc2264d9ffd3b335c7396667e45f537ff1f75ed5afa00585db274f3b6",
26+
case: :mixed
27+
)
28+
29+
private_key =
30+
Base.decode16!("18363054f52f3f1fdc9ae50d271de853c582c652ebe8dd0f261da3b00cd98984",
31+
case: :mixed
32+
)
33+
34+
assert Bls.derive_pubkey(private_key) == {:ok, valid_public_key}
35+
end
36+
end
2037
end

0 commit comments

Comments
 (0)