-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
175 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
0448c07c3724c9a4fa9b002f12cf326136433625b27f35da8d992a4f4b5688627fbf3705da7042d1bb8c74b719d62f89c889bb45876efcc7faced3f28f5e54969804545f5da84824570e3710dc88c0f1303db91e4b7ff0ee17fe41c66c954d8bcddc4f74910117620565061c7e84a05d13b681e75c90d7ddc0b369a7000cef85367c |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
04bff189bf2177cca7618f09acef5129064d43956d334bedf61cd117c996e5c17f66937dc07f0f18c7d47d2af937e1bd56bd10f71e513dc8d1d218cc39fdeaae3304c849c5e8bb24962b8339cf566ce6853faa754cffa3886919defde706d875d27903808b53677813d27dd1bc985c1d38d21181568adb2ae3c8a7789e9e37e6577f |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
048e92f6cdcc0b375505980a298d9b79201db1f08b1f135360d2864af1a67186ec0dbeb570d396a456226b0844be93dbc0180abbf7e2e4c9cfde8d5da4e3f8a49004f3422b8afbe425d6ece77b8d2469954715a2ff273ab7ac89f1ed70e0a9325eaa1698b4351fd1b23734e65c0b6a86b62dd49d70b37c94606aac402cbd84353212 |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
04603e5bd2e15714e162b5adad657cc0bd26b8d92a1c8d255b148911a834ac1be5c9a76720aac5ec80a49b6b26c48c4bcecf828f9986e1550c829250566ae14fa40445a0e4b7e2672556492c493b2cc0b9894bee5ca4ee37bae0b717930b0e970cd4922417c326c348a669863c4385dd0676cc8f53c8b6f3692e6c31481ac022735d |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
04296d80de8593982b0a70a8cc03f4ae664433df5e091c5555d6f49311b4dba1f5c8073565f6b1f2a17ad274b0e7f50f826431f3d5e47ad1cb5e64ea893ce6409f04044ece64c3cea982c7859398ad7d79462d8e35db1173deac68fe173e9585b8acdd43c24902e4e965f6f45f4ba37ce15394e863d4a20c2094ddeea573c66d3554 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
//! Utility script to reshard old dev shares into 2 pieces. | ||
//! This lets us test "true" quorum settings instead of relying on a 1-out-of-1 | ||
//! quorum. | ||
use std::{ | ||
fs, | ||
path::Path, | ||
process::Command, | ||
time::{SystemTime, UNIX_EPOCH}, | ||
}; | ||
|
||
use qos_crypto::shamir::shares_generate; | ||
use qos_p256::{ | ||
derive_secret, encrypt::P256EncryptPair, P256Pair, P256_ENCRYPT_DERIVE_PATH, | ||
}; | ||
|
||
// Note: the dev secret is NOT checked in QOS. It can be found in our keys repo | ||
// (tkhq/keys:deployment/preprod/evm-parser/manifest-set/dev.secret) This secret | ||
// is not security sensitive since it belongs to our dev/preprod environment but | ||
// I want to avoid duplicating it in case there's drift for whatever reason. | ||
// However I've choosen to commit the old encrypted shares and quorum public | ||
// keys because they're useful anchors for this tests. The quorum public keys | ||
// and old dev shares for each enclaves are committed in | ||
// ./fixtures/preprod/$ENCLAVE_NAME/ | ||
const OLD_DEV_SECRET_PATH: &str = "./fixtures/preprod/old_dev.secret"; | ||
|
||
#[test] | ||
fn preprod_reshard_ceremony() { | ||
// Global setup: our test will write to a new folder in `/tmp` | ||
let unix_timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); | ||
let tmp_dir = | ||
format!("/tmp/preprod-reshard-{}", unix_timestamp.as_millis()); | ||
fs::create_dir_all(&tmp_dir).unwrap(); | ||
|
||
let tmp_path = |file: &str| -> String { format!("{}/{file}", tmp_dir) }; | ||
|
||
let dev_users_dir = tmp_path("dev-users"); | ||
fs::create_dir_all(dev_users_dir.clone()).unwrap(); | ||
|
||
let enclaves_dir = tmp_path("enclaves"); | ||
fs::create_dir_all(enclaves_dir.clone()).unwrap(); | ||
|
||
let user_dir = |user: &str| format!("{}/{}", dev_users_dir, user); | ||
let enclave_dir = |enclave: &str| format!("{}/{}", enclaves_dir, enclave); | ||
let get_key_paths = | ||
|user: &str| (format!("{user}.secret"), format!("{user}.pub")); | ||
|
||
let user1 = "1"; | ||
let (user1_private_path, user1_public_path) = get_key_paths(user1); | ||
|
||
let user2 = "2"; | ||
let (user2_private_path, user2_public_path) = get_key_paths(user2); | ||
|
||
// Generate user directories and keys | ||
for (user, private, public) in [ | ||
(&user1, &user1_private_path, &user1_public_path), | ||
(&user2, &user2_private_path, &user2_public_path), | ||
] { | ||
fs::create_dir_all(user_dir(user)).unwrap(); | ||
|
||
let master_seed_path = format!("{}/{}", user_dir(user), private); | ||
let public_path = format!("{}/{}", user_dir(user), public); | ||
assert!(Command::new("../target/debug/qos_client") | ||
.args([ | ||
"generate-file-key", | ||
"--master-seed-path", | ||
&master_seed_path, | ||
"--pub-path", | ||
&public_path, | ||
]) | ||
.spawn() | ||
.unwrap() | ||
.wait() | ||
.unwrap() | ||
.success()); | ||
|
||
// Assert both public and private key paths now exist | ||
assert!(Path::new(&*user_dir(user)).join(public).is_file()); | ||
assert!(Path::new(&*user_dir(user)).join(private).is_file()); | ||
} | ||
|
||
// Load previous dev secret (1/1 setting) | ||
let dev_secret_utf8_bytes = fs::read(OLD_DEV_SECRET_PATH).expect("Cannot read old dev secret. Did you add it to at ./fixtures/preprod/old_dev.secret?"); | ||
let dev_secret_hex_bytes = | ||
qos_hex::decode(std::str::from_utf8(&dev_secret_utf8_bytes).unwrap()) | ||
.unwrap(); | ||
let dev_key = P256Pair::from_master_seed( | ||
&dev_secret_hex_bytes.clone().try_into().unwrap(), | ||
) | ||
.unwrap(); | ||
|
||
// For each of the enclaves... | ||
for enclave_name in | ||
["ump", "evm-parser", "notarizer", "signer", "tls-fetcher"] | ||
{ | ||
// Decrypt the old dev share and assert that the resulting quorum key | ||
// has the right public key. Decrypted dev shares are _basically_ master | ||
// seeds. They're just have a "01" prefix because it's the one and only | ||
// "share" in a 1/1 SSS sharing. | ||
let encrypted_old_dev_share = fs::read(format!( | ||
"./fixtures/preprod/{}/old_dev.share.keep", | ||
enclave_name | ||
)) | ||
.unwrap(); | ||
let mut decrypted_dev_share = | ||
dev_key.decrypt(&encrypted_old_dev_share).unwrap(); | ||
let removed_byte = decrypted_dev_share.remove(0); | ||
assert_eq!(removed_byte, 1); | ||
|
||
let pk = P256Pair::from_master_seed( | ||
&decrypted_dev_share.clone().try_into().unwrap(), | ||
) | ||
.unwrap() | ||
.public_key(); | ||
let expected_quorum_public_key = fs::read(format!( | ||
"./fixtures/preprod/{}/quorum_key.pub", | ||
enclave_name | ||
)) | ||
.unwrap(); | ||
assert_eq!( | ||
qos_hex::encode(&pk.to_bytes()), | ||
std::str::from_utf8(&expected_quorum_public_key).unwrap() | ||
); | ||
|
||
// Now we have the proper quorum key, we're ready to shard it in two | ||
// pieces, to our two new users. | ||
let new_shares = shares_generate(&decrypted_dev_share, 2, 2).unwrap(); // (threshold, total) | ||
assert_eq!(new_shares.len(), 2); | ||
|
||
for (user, share) in | ||
[(&user1, &new_shares[0]), (&user2, &new_shares[1])] | ||
{ | ||
// Load the key pair for this user | ||
let user_secret_path = | ||
format!("{}/{}.secret", user_dir(user), user); | ||
let user_key_pair = | ||
P256Pair::from_hex_file(user_secret_path.clone()).unwrap(); | ||
// Encrypt the new share to it | ||
let encrypted_share = | ||
user_key_pair.public_key().encrypt(share).unwrap(); | ||
|
||
// And write the resulting file | ||
fs::create_dir_all(enclave_dir(enclave_name)).unwrap(); | ||
let encrypted_share_path = | ||
format!("{}/{}.share", enclave_dir(enclave_name), user); | ||
fs::write(encrypted_share_path.clone(), encrypted_share).unwrap(); | ||
|
||
// Just to make sure: can the user decrypt the share we just created | ||
// with their secret? | ||
assert_can_decrypt(user_secret_path, encrypted_share_path); | ||
} | ||
} | ||
|
||
println!("success, reshard complete. Outputs are in {}", tmp_dir); | ||
} | ||
|
||
// Helper function to assert a given user secret (1st arg) can decrypt a share | ||
// (2nd arg) | ||
fn assert_can_decrypt(user_secret_path: String, sharepath: String) { | ||
let share = fs::read(sharepath).unwrap(); | ||
let master_seed_hex_bytes = fs::read(user_secret_path).unwrap(); | ||
let master_seed_utf8 = std::str::from_utf8(&master_seed_hex_bytes).unwrap(); | ||
let master_seed = qos_hex::decode(master_seed_utf8).unwrap(); | ||
let encryption_pair_secret = derive_secret( | ||
&master_seed.try_into().unwrap(), | ||
P256_ENCRYPT_DERIVE_PATH, | ||
) | ||
.unwrap(); | ||
let pair = P256EncryptPair::from_bytes(&encryption_pair_secret).unwrap(); | ||
assert!(pair.decrypt(&share).is_ok()); | ||
} |