Skip to content

Commit df225a3

Browse files
committed
add support for multiple keysets
1 parent 767ed51 commit df225a3

File tree

4 files changed

+23
-17
lines changed

4 files changed

+23
-17
lines changed

fb_recover_keys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def main():
118118
for algo, info in privkeys.items():
119119
# info may be either None or tuple
120120
if info:
121-
privkey, chaincode = info
121+
privkey, chaincode, keyset_id = info
122122
pub = recover.get_public_key(algo, privkey)
123123
if show_xprv:
124124
print(privkey_descriptions[algo] + ":\t" + recover.encode_extended_key(algo, privkey, chaincode, False))

test/test_recovery.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
def test_recovery_basic():
99
result = recover.restore_key_and_chaincode(TEST_DIR / "backup.zip", TEST_DIR / "priv.pem", "Thefireblocks1!")
1010

11-
ecdsa_priv_key, ecdsa_chaincode = result['MPC_ECDSA_SECP256K1']
11+
ecdsa_priv_key, ecdsa_chaincode, _ = result['MPC_ECDSA_SECP256K1']
1212
assert(ecdsa_priv_key == 0x473d1820ca4bf7cf6b018a8520b1ec0849cb99bce4fff45c5598723f67b3bd52)
1313
pub = recover.get_public_key("MPC_ECDSA_SECP256K1", ecdsa_priv_key)
1414
assert(pub == "021d84f3b6d7c6888f81c7cc381b658d85319f27e1ea9c93dff128667fb4b82ba0")
@@ -18,8 +18,8 @@ def test_recovery_basic():
1818

1919
def test_full_recovery():
2020
result = recover.restore_key_and_chaincode(TEST_DIR / "backup_new.zip", TEST_DIR / "priv2.pem", "Thefireblocks1!")
21-
ecdsa_priv_key, ecdsa_chaincode = result['MPC_ECDSA_SECP256K1']
22-
eddsa_priv_key, eddsa_chaincode = result['MPC_EDDSA_ED25519']
21+
ecdsa_priv_key, ecdsa_chaincode, _ = result['MPC_ECDSA_SECP256K1']
22+
eddsa_priv_key, eddsa_chaincode, _ = result['MPC_EDDSA_ED25519']
2323

2424
assert(ecdsa_priv_key == 0x66b1baf063db6e7152480334ebab0ab098e85f682b784754e46c18c962a1aa9d)
2525
assert(eddsa_priv_key == 0xd74820d02cc2aa09e2d0bcb36aeb92625b3d92c8d202063eab5513fd4453a44)
@@ -39,7 +39,7 @@ def test_full_recovery():
3939

4040
def test_recovery_old_format():
4141
result = recover.restore_key_and_chaincode(TEST_DIR / "backup_old_format.zip", TEST_DIR / "priv.pem", "Thefireblocks1!")
42-
ecdsa_priv_key, ecdsa_chaincode = result['MPC_ECDSA_SECP256K1']
42+
ecdsa_priv_key, ecdsa_chaincode, _ = result['MPC_ECDSA_SECP256K1']
4343

4444
assert(ecdsa_priv_key == 0x473d1820ca4bf7cf6b018a8520b1ec0849cb99bce4fff45c5598723f67b3bd52)
4545
pub = recover.get_public_key("MPC_ECDSA_SECP256K1", ecdsa_priv_key)
@@ -50,8 +50,8 @@ def test_recovery_old_format():
5050

5151
def test_cmp_recovery():
5252
result = recover.restore_key_and_chaincode(TEST_DIR / "backup_cmp.zip", TEST_DIR / "priv.pem", "Fireblocks1!")
53-
ecdsa_priv_key, ecdsa_chaincode = result['MPC_CMP_ECDSA_SECP256K1']
54-
eddsa_priv_key, eddsa_chaincode = result['MPC_CMP_EDDSA_ED25519']
53+
ecdsa_priv_key, ecdsa_chaincode, _ = result['MPC_CMP_ECDSA_SECP256K1']
54+
eddsa_priv_key, eddsa_chaincode, _ = result['MPC_CMP_EDDSA_ED25519']
5555

5656
assert(ecdsa_priv_key == 0xf57c18e98a24ca0b36fbbd103233aff128b740426da189ce208545d44bbad050)
5757
assert(eddsa_priv_key == 0xa536dc2f2d744ae78eb26fdfb4b9e234a649525e0a1142bf900cd9c26987007)
@@ -77,8 +77,8 @@ def test_one_custom_chaincode_recovery():
7777
which encodes the chaincode.
7878
'''
7979
result = recover.restore_key_and_chaincode(TEST_DIR / "backup_with_one_custom_chaincode.zip", TEST_DIR / "priv2.pem", "Thefireblocks1!")
80-
ecdsa_priv_key, ecdsa_chaincode = result['MPC_ECDSA_SECP256K1']
81-
eddsa_priv_key, eddsa_chaincode = result['MPC_EDDSA_ED25519']
80+
ecdsa_priv_key, ecdsa_chaincode, _ = result['MPC_ECDSA_SECP256K1']
81+
eddsa_priv_key, eddsa_chaincode, _ = result['MPC_EDDSA_ED25519']
8282

8383
assert(ecdsa_chaincode != eddsa_chaincode)
8484
assert(ecdsa_priv_key == 0x66b1baf063db6e7152480334ebab0ab098e85f682b784754e46c18c962a1aa9d)
@@ -111,8 +111,8 @@ def test_two_custom_chaincode_recovery():
111111
112112
'''
113113
result = recover.restore_key_and_chaincode(TEST_DIR / "backup_with_two_custom_chaincode.zip", TEST_DIR / "priv2.pem", "Thefireblocks1!")
114-
ecdsa_priv_key, ecdsa_chaincode = result['MPC_ECDSA_SECP256K1']
115-
eddsa_priv_key, eddsa_chaincode = result['MPC_EDDSA_ED25519']
114+
ecdsa_priv_key, ecdsa_chaincode, _ = result['MPC_ECDSA_SECP256K1']
115+
eddsa_priv_key, eddsa_chaincode, _ = result['MPC_EDDSA_ED25519']
116116

117117
assert(ecdsa_chaincode != eddsa_chaincode)
118118
assert(ecdsa_priv_key == 0x66b1baf063db6e7152480334ebab0ab098e85f682b784754e46c18c962a1aa9d)
@@ -133,8 +133,8 @@ def test_two_custom_chaincode_recovery():
133133

134134
def test_recovery_with_mobile_share_as_json():
135135
result = recover.restore_key_and_chaincode(TEST_DIR / "json_share.zip", TEST_DIR / "priv.pem", "Fireblocks1!")
136-
ecdsa_priv_key, ecdsa_chaincode = result['MPC_CMP_ECDSA_SECP256K1']
137-
eddsa_priv_key, eddsa_chaincode = result['MPC_EDDSA_ED25519']
136+
ecdsa_priv_key, ecdsa_chaincode, _ = result['MPC_CMP_ECDSA_SECP256K1']
137+
eddsa_priv_key, eddsa_chaincode, _ = result['MPC_EDDSA_ED25519']
138138

139139
assert(ecdsa_priv_key == 0x83af98f2f2bdea33eb34177b311d89569725a401c1fc4d6046d266b1ca0dc382)
140140
assert(eddsa_priv_key == 0xd5c4d44f0f07aaa0bf18e039f28ec2131935ed696636f48ec46bab58e66296b)
@@ -154,8 +154,8 @@ def test_recovery_with_mobile_share_as_json():
154154

155155
def test_recovery_with_master_keys():
156156
result = recover.restore_key_and_chaincode(TEST_DIR / "backup_with_master_key.zip", TEST_DIR / "priv_ncw.pem", "2#0Iw0Qov@&QP09p", key_pass="SECRET")
157-
ecdsa_priv_key, ecdsa_chaincode = result["MPC_CMP_ECDSA_SECP256K1"]
158-
eddsa_priv_key, eddsa_chaincode = result["MPC_EDDSA_ED25519"]
157+
ecdsa_priv_key, ecdsa_chaincode, _ = result["MPC_CMP_ECDSA_SECP256K1"]
158+
eddsa_priv_key, eddsa_chaincode, _ = result["MPC_EDDSA_ED25519"]
159159

160160
pub = recover.get_public_key("MPC_ECDSA_SECP256K1", ecdsa_priv_key)
161161
assert pub == "033f5e4fb621e4cc777e5b9cdc0ef06c7b55042e9ce6c3bf013daab9fba29b37b8"

utils/metadata.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class SigningKeyMetadata:
1717
public_key: str
1818
algorithm: str
1919
chain_code: bytes
20+
keyset_id: int
2021

2122

2223
@dataclass
@@ -55,13 +56,18 @@ def parse_metadata_file(fp: IO[bytes]) -> RecoveryPackageMetadata:
5556
else:
5657
chain_code_for_this_key = default_chain_code
5758

59+
keyset_id_for_this_key = 1
60+
if "keysetId" in key_metadata:
61+
keyset_id_for_this_key = int(key_metadata["keysetId"])
62+
5863
if len(chain_code_for_this_key) != 32:
5964
raise RecoveryErrorUnknownChainCode()
6065

6166
signing_keys[key_id] = SigningKeyMetadata(
6267
public_key=metadata_public_key,
6368
algorithm=algo,
64-
chain_code=chain_code_for_this_key
69+
chain_code=chain_code_for_this_key,
70+
keyset_id=keyset_id_for_this_key
6571
)
6672

6773
master_keys_in_backup = obj.get("masterKeys", {})

utils/recover.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ def restore_key_and_chaincode(zip_path, private_pem_path, passphrase, key_pass=N
239239
print(f"Failed to recover {algo} key, expected public key is: {pub_from_metadata} calculated public key is: {pubkey_str}")
240240
privkeys[algo] = None
241241
else:
242-
privkeys[algo] = privkey, chain_code_for_this_key
242+
privkeys[algo] = privkey, chain_code_for_this_key, signing_keys[key_id].keyset_id
243243

244244
if len(privkeys) == 0:
245245
raise RecoveryErrorPublicKeyNoMatch()

0 commit comments

Comments
 (0)