diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e9651c1..0367691d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,9 @@ jobs: - uses: actions/checkout@v4 - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }} + # For keyring dependencies + - run: sudo apt install libdbus-1-dev pkg-config + - name: Cache Docker layers id: image-cache uses: actions/cache@v4 @@ -75,6 +78,8 @@ jobs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/main' }} + # For keyring dependencies + - run: sudo apt install libdbus-1-dev pkg-config - name: Install r0vm run: | wget https://github.com/risc0/risc0/releases/download/v1.3.0/cargo-risczero-x86_64-unknown-linux-gnu.tgz @@ -103,6 +108,8 @@ jobs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/main' }} + # For keyring dependencies + - run: sudo apt install libdbus-1-dev pkg-config - name: Build model run: cargo build -p hyle-model --no-default-features - name: Build diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 3e9b69db..ef4c0200 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -16,6 +16,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + # For keyring dependencies + - run: sudo apt install libdbus-1-dev pkg-config - uses: actions-rs/toolchain@v1 with: toolchain: stable diff --git a/Cargo.lock b/Cargo.lock index 5034e071..8393a9f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1538,6 +1538,30 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + +[[package]] +name = "dbus-secret-service" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" +dependencies = [ + "dbus", + "futures-util", + "num", + "once_cell", + "rand 0.8.5", +] + [[package]] name = "der" version = "0.7.9" @@ -2623,6 +2647,7 @@ dependencies = [ "hyle-verifiers", "hyllar", "indexmap 2.7.1", + "keyring", "opentelemetry", "opentelemetry-prometheus", "opentelemetry_sdk", @@ -2656,6 +2681,7 @@ dependencies = [ "utoipa-axum", "utoipa-swagger-ui", "uuid-tld", + "whoami", ] [[package]] @@ -3208,6 +3234,20 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keyring" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8fe839464d4e4b37d756d7e910063696af79a7e877282cb1825e4ec5f10833" +dependencies = [ + "byteorder", + "dbus-secret-service", + "log", + "security-framework 2.11.1", + "security-framework 3.2.0", + "windows-sys 0.59.0", +] + [[package]] name = "lazy-regex" version = "3.4.1" @@ -3246,6 +3286,15 @@ version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "pkg-config", +] + [[package]] name = "libloading" version = "0.8.6" @@ -7832,6 +7881,7 @@ checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ "redox_syscall 0.5.9", "wasite", + "web-sys", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index cf96b33c..2dfe5c7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,6 +133,8 @@ utoipa = { version = "5.3.1", features = ["axum_extras"] } utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] } utoipa-axum = { version = "0.2.0" } testcontainers-modules = { version = "0.11.6", features = ["postgres"] } +keyring = { version = "3", features = ["apple-native", "windows-native", "sync-secret-service"] } +whoami = "1.5.2" [dev-dependencies] amm = { path = "./crates/contracts/amm", features = ["client"] } diff --git a/src/bin/hyle.rs b/src/bin/hyle.rs index 37689d9f..2a1fcc4d 100644 --- a/src/bin/hyle.rs +++ b/src/bin/hyle.rs @@ -72,7 +72,7 @@ async fn main() -> Result<()> { let mut config = conf::Conf::new(args.config_file, args.data_directory, args.run_indexer) .context("reading config file")?; - let crypto = Arc::new(BlstCrypto::new(config.id.clone()).context("Could not create crypto")?); + let crypto = Arc::new(BlstCrypto::new(&config.id).context("Could not create crypto")?); let pubkey = Some(crypto.validator_pubkey().clone()); setup_tracing( @@ -88,6 +88,8 @@ async fn main() -> Result<()> { ), )?; + info!("Loaded key {:?} for validator", pubkey); + let pg; if args.pg { if std::fs::metadata(&config.data_directory).is_ok() { diff --git a/src/consensus.rs b/src/consensus.rs index 32052601..0a8b589a 100644 --- a/src/consensus.rs +++ b/src/consensus.rs @@ -1166,7 +1166,7 @@ pub mod test { } async fn new_node(name: &str) -> Self { - let crypto = crypto::BlstCrypto::new(name.into()).unwrap(); + let crypto = crypto::BlstCrypto::new(name).unwrap(); Self::new(name, crypto.clone()).await } diff --git a/src/genesis.rs b/src/genesis.rs index d0dbb937..5558dede 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -545,7 +545,7 @@ mod tests { let shared_bus = SharedMessageBus::default(); let bus = GenesisBusClient::new_from_bus(shared_bus.new_handle()).await; let test_bus = TestGenesisBusClient::new_from_bus(shared_bus.new_handle()).await; - let crypto = Arc::new(BlstCrypto::new(config.id.clone()).unwrap()); + let crypto = Arc::new(BlstCrypto::new(&config.id).unwrap()); ( Genesis { config: Arc::new(config), @@ -705,7 +705,7 @@ mod tests { let (mut genesis, mut bus) = new(config.clone()).await; bus.send(PeerEvent::NewPeer { name: "node-2".into(), - pubkey: BlstCrypto::new("node-2".into()) + pubkey: BlstCrypto::new("node-2") .unwrap() .validator_pubkey() .clone(), @@ -714,7 +714,7 @@ mod tests { .expect("send"); bus.send(PeerEvent::NewPeer { name: "node-3".into(), - pubkey: BlstCrypto::new("node-3".into()) + pubkey: BlstCrypto::new("node-3") .unwrap() .validator_pubkey() .clone(), @@ -723,7 +723,7 @@ mod tests { .expect("send"); bus.send(PeerEvent::NewPeer { name: "node-4".into(), - pubkey: BlstCrypto::new("node-4".into()) + pubkey: BlstCrypto::new("node-4") .unwrap() .validator_pubkey() .clone(), @@ -739,7 +739,7 @@ mod tests { let (mut genesis, mut bus) = new(config).await; bus.send(PeerEvent::NewPeer { name: "node-4".into(), - pubkey: BlstCrypto::new("node-4".into()) + pubkey: BlstCrypto::new("node-4") .unwrap() .validator_pubkey() .clone(), @@ -748,7 +748,7 @@ mod tests { .expect("send"); bus.send(PeerEvent::NewPeer { name: "node-2".into(), - pubkey: BlstCrypto::new("node-2".into()) + pubkey: BlstCrypto::new("node-2") .unwrap() .validator_pubkey() .clone(), @@ -757,7 +757,7 @@ mod tests { .expect("send"); bus.send(PeerEvent::NewPeer { name: "node-3".into(), - pubkey: BlstCrypto::new("node-3".into()) + pubkey: BlstCrypto::new("node-3") .unwrap() .validator_pubkey() .clone(), diff --git a/src/mempool.rs b/src/mempool.rs index 5bb770ef..10a40dd7 100644 --- a/src/mempool.rs +++ b/src/mempool.rs @@ -1239,7 +1239,7 @@ pub mod test { } pub async fn new(name: &str) -> Self { - let crypto = BlstCrypto::new(name.into()).unwrap(); + let crypto = BlstCrypto::new(name).unwrap(); let shared_bus = SharedMessageBus::new(BusMetrics::global("global".to_string())); let out_receiver = get_receiver::(&shared_bus).await; @@ -1626,10 +1626,10 @@ pub mod test { // Adding 4 other validators // Total voting_power = 500; f = 167 --> You need at least 2 signatures to send PoDAUpdate - let crypto2 = BlstCrypto::new("validator2".into()).unwrap(); - let crypto3 = BlstCrypto::new("validator3".into()).unwrap(); - let crypto4 = BlstCrypto::new("validator4".into()).unwrap(); - let crypto5 = BlstCrypto::new("validator5".into()).unwrap(); + let crypto2 = BlstCrypto::new("validator2").unwrap(); + let crypto3 = BlstCrypto::new("validator3").unwrap(); + let crypto4 = BlstCrypto::new("validator4").unwrap(); + let crypto5 = BlstCrypto::new("validator5").unwrap(); ctx.setup_node(&[pubkey, crypto2.clone(), crypto3.clone(), crypto4, crypto5]); let register_tx = make_register_contract_tx(ContractName::new("test1")); @@ -1668,7 +1668,7 @@ pub mod test { ctx.setup_node(&[pubkey]); // Adding new validator - let temp_crypto = BlstCrypto::new("validator1".into()).unwrap(); + let temp_crypto = BlstCrypto::new("validator1").unwrap(); ctx.add_trusted_validator(temp_crypto.validator_pubkey()); // Sending transaction to mempool as RestApiMessage @@ -1764,7 +1764,7 @@ pub mod test { ); let size = LaneBytesSize(data_proposal.estimate_size() as u64); - let temp_crypto = BlstCrypto::new("temp_crypto".into()).unwrap(); + let temp_crypto = BlstCrypto::new("temp_crypto").unwrap(); let signed_msg = temp_crypto.sign(MempoolNetMessage::DataVote(data_proposal.hashed(), size))?; assert!(ctx @@ -1797,7 +1797,7 @@ pub mod test { ctx.make_data_proposal_with_pending_txs()?; // Add new validator - let crypto2 = BlstCrypto::new("2".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); ctx.add_trusted_validator(crypto2.validator_pubkey()); let signed_msg = crypto2.sign(MempoolNetMessage::DataVote( @@ -1833,7 +1833,7 @@ pub mod test { ctx.make_data_proposal_with_pending_txs()?; // Add new validator - let crypto2 = BlstCrypto::new("2".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); ctx.add_trusted_validator(crypto2.validator_pubkey()); let signed_msg = crypto2.sign(MempoolNetMessage::DataVote( @@ -1848,7 +1848,7 @@ pub mod test { #[test_log::test(tokio::test)] async fn test_sending_sync_request() -> Result<()> { let mut ctx = MempoolTestCtx::new("mempool").await; - let crypto2 = BlstCrypto::new("2".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); let pubkey2 = crypto2.validator_pubkey(); ctx.handle_consensus_event(ConsensusProposal { @@ -1889,7 +1889,7 @@ pub mod test { ctx.last_validator_lane_entry(ctx.validator_pubkey()); // Add new validator - let crypto2 = BlstCrypto::new("2".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); ctx.add_trusted_validator(crypto2.validator_pubkey()); let signed_msg = crypto2.sign(MempoolNetMessage::SyncRequest( @@ -1935,8 +1935,8 @@ pub mod test { ) = ctx.last_validator_lane_entry(ctx.validator_pubkey()); // Add new validator - let crypto2 = BlstCrypto::new("2".into()).unwrap(); - let crypto3 = BlstCrypto::new("3".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); + let crypto3 = BlstCrypto::new("3").unwrap(); ctx.add_trusted_validator(crypto2.validator_pubkey()); diff --git a/src/mempool/storage.rs b/src/mempool/storage.rs index 8645a0dd..75d470e8 100644 --- a/src/mempool/storage.rs +++ b/src/mempool/storage.rs @@ -630,7 +630,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_put_contains_get() { - let crypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -653,7 +653,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_update() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); let data_proposal = DataProposal::new(None, vec![]); @@ -679,10 +679,10 @@ mod tests { #[test_log::test(tokio::test)] async fn test_on_data_proposal() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); - let crypto2: BlstCrypto = crypto::BlstCrypto::new("2".to_owned()).unwrap(); + let crypto2: BlstCrypto = crypto::BlstCrypto::new("2").unwrap(); let pubkey2 = crypto2.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -708,10 +708,10 @@ mod tests { #[test_log::test(tokio::test)] async fn test_on_data_proposal_fork() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); - let crypto2: BlstCrypto = crypto::BlstCrypto::new("2".to_owned()).unwrap(); + let crypto2: BlstCrypto = crypto::BlstCrypto::new("2").unwrap(); let pubkey2 = crypto2.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -738,11 +738,11 @@ mod tests { #[test_log::test(tokio::test)] async fn test_on_data_vote() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); - let crypto2: BlstCrypto = crypto::BlstCrypto::new("2".to_owned()).unwrap(); + let crypto2: BlstCrypto = crypto::BlstCrypto::new("2").unwrap(); let data_proposal = DataProposal::new(None, vec![]); // 1 creates a DP @@ -766,13 +766,13 @@ mod tests { #[test_log::test(tokio::test)] async fn test_on_poda_update() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); - let crypto2: BlstCrypto = crypto::BlstCrypto::new("2".to_owned()).unwrap(); + let crypto2: BlstCrypto = crypto::BlstCrypto::new("2").unwrap(); let pubkey2 = crypto2.validator_pubkey(); - let crypto3: BlstCrypto = crypto::BlstCrypto::new("3".to_owned()).unwrap(); + let crypto3: BlstCrypto = crypto::BlstCrypto::new("3").unwrap(); let dp = DataProposal::new(None, vec![]); @@ -799,7 +799,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_get_lane_entries_between_hashes() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); let dp1 = DataProposal::new(None, vec![]); @@ -862,7 +862,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_new_data_proposal() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -882,7 +882,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_new_data_proposal_empty() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -898,7 +898,7 @@ mod tests { #[test_log::test] fn test_lane_size() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -929,7 +929,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_get_lane_pending_entries() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); let data_proposal = DataProposal::new(None, vec![]); @@ -946,7 +946,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_get_latest_car_and_new_cut() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); let staking = Staking::new(); diff --git a/src/single_node_consensus.rs b/src/single_node_consensus.rs index 4562ec23..5b7e3b3c 100644 --- a/src/single_node_consensus.rs +++ b/src/single_node_consensus.rs @@ -236,7 +236,7 @@ mod tests { impl TestContext { pub async fn new(name: &str) -> Self { - let crypto = BlstCrypto::new(name.into()).unwrap(); + let crypto = BlstCrypto::new(name).unwrap(); let shared_bus = SharedMessageBus::new(BusMetrics::global("global".to_string())); let conf = Arc::new(Conf::default()); let store = SingleNodeConsensusStore::default(); diff --git a/src/tests/autobahn_testing.rs b/src/tests/autobahn_testing.rs index 16158935..ab73c9b3 100644 --- a/src/tests/autobahn_testing.rs +++ b/src/tests/autobahn_testing.rs @@ -274,7 +274,7 @@ impl AutobahnTestCtx { pub fn generate_cryptos(nb: usize) -> Vec { (0..nb) .map(|i| { - let crypto = crypto::BlstCrypto::new(format!("node-{i}")).unwrap(); + let crypto = crypto::BlstCrypto::new(&format!("node-{i}")).unwrap(); info!("node {}: {}", i, crypto.validator_pubkey()); crypto }) @@ -730,7 +730,7 @@ async fn autobahn_rejoin_flow() { 0, ); - let crypto = crypto::BlstCrypto::new("node-3".to_owned()).unwrap(); + let crypto = crypto::BlstCrypto::new("node-3").unwrap(); let mut joining_node = AutobahnTestCtx::new("node-3", crypto).await; joining_node .consensus_ctx diff --git a/src/utils/crypto.rs b/src/utils/crypto.rs index cf0f234a..27213580 100644 --- a/src/utils/crypto.rs +++ b/src/utils/crypto.rs @@ -1,3 +1,30 @@ +//! # BlstCrypto +//! +//! The `BlstCrypto` struct is used to manage cryptographic keys and operations. +//! +//! ## Initialization +//! +//! The function `new` is used to initialize a `BlstCrypto` instance. The behavior of this function depends on the environment: +//! +//! ```rust +//! use crate::utils::crypto::BlstCrypto; +//! +//! let validator_name = String::from("validator_name"); +//! let crypto = BlstCrypto::new(validator_name).expect("Failed to initialize BlstCrypto"); +//! ``` +//! +//! ### Non-Test Environment +//! +//! This module load the private key seed from the environment variable `HYLE_VALIDATOR_SECRET`. +//! The content of the variable must be a hexadecimal string. +//! If the variable is not set, it tries to load the key from the keyring. +//! +//! Note: you can use tools like seahorse (https://wiki.gnome.org/Apps/Seahorse) to manage your keyring +//! +//! ### Test Environment +//! +//! In a test environment the modules generates a secret key based on the validator name, which is less secure but suitable for testing purposes. +//! #![allow(dead_code, unused_variables)] use std::sync::Arc; @@ -30,14 +57,56 @@ const DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; pub const SIG_SIZE: usize = 48; impl BlstCrypto { - pub fn new(validator_name: String) -> Result { - // TODO load secret key from keyring or other + #[cfg(not(test))] + pub fn new(validator_name: &str) -> Result { + let sk = Self::load_from_env().or_else(|err| { + println!("Could not load secret from env: {}", err); + Self::load_from_keyring(validator_name) + })?; + + let validator_pubkey = as_validator_pubkey(sk.sk_to_pk()); + + Ok(BlstCrypto { + sk, + validator_pubkey, + }) + } + + /// Load the secret key from the environment variable `HYLE_VALIDATOR_SECRET`. + #[cfg(not(test))] + fn load_from_env() -> Result { + let secret = std::env::var("HYLE_VALIDATOR_SECRET") + .map_err(|_| anyhow!("HYLE_VALIDATOR_SECRET not set"))?; + SecretKey::key_gen(&hex::decode(secret)?, &[]) + .map_err(|e| anyhow!("Could not generate key from keyring secret: {:?}", e)) + } + + /// Load the secret key from the keyring. If the key does not exist, a new random one is generated. + #[cfg(not(test))] + fn load_from_keyring(validator_name: &str) -> Result { + let user = whoami::username(); + let entry = keyring::Entry::new_with_target("hyle", validator_name, &user)?; + + let sk = match entry.get_password() { + Ok(secret) => SecretKey::key_gen(&hex::decode(secret)?, &[]) + .map_err(|e| anyhow!("Could not generate key from keyring secret: {:?}", e))?, + Err(keyring::Error::NoEntry) => { + let mut ikm = [0u8; 32]; + rand::rng().fill(&mut ikm); + entry.set_password(&hex::encode(ikm))?; + SecretKey::key_gen(&ikm, &[]) + .map_err(|e| anyhow!("Could not generate new key: {:?}", e))? + } + Err(e) => bail!("Could not get secret: {:?}", e), + }; + + Ok(sk) + } + + #[cfg(test)] + pub fn new(validator_name: &str) -> Result { // here basically secret_key <=> validator_id which is very badly secure ! - let validator_name_bytes = validator_name.as_bytes(); - let mut ikm = [0u8; 32]; - let len = std::cmp::min(validator_name_bytes.len(), 32); - #[allow(clippy::indexing_slicing, reason = "len checked")] - ikm[..len].copy_from_slice(&validator_name_bytes[..len]); + let ikm = Self::secret_from_name(validator_name); let sk = SecretKey::key_gen(&ikm, &[]) .map_err(|e| anyhow!("Could not generate key: {:?}", e))?; @@ -49,12 +118,22 @@ impl BlstCrypto { }) } + pub fn secret_from_name(validator_name: &str) -> [u8; 32] { + let validator_name_bytes = validator_name.as_bytes(); + let mut ikm = [0u8; 32]; + let len = std::cmp::min(validator_name_bytes.len(), 32); + #[allow(clippy::indexing_slicing, reason = "len checked")] + ikm[..len].copy_from_slice(&validator_name_bytes[..len]); + ikm + } + + #[cfg(test)] pub fn new_random() -> Result { let mut rng = rand::rng(); let id: String = (0..32) .map(|_| rng.random_range(33..127) as u8 as char) // Caractères imprimables ASCII .collect(); - Self::new(id.as_str().into()) + Self::new(id.as_str()) } pub fn validator_pubkey(&self) -> &ValidatorPublicKey { diff --git a/src/utils/integration_test.rs b/src/utils/integration_test.rs index 0f265386..6df9335a 100644 --- a/src/utils/integration_test.rs +++ b/src/utils/integration_test.rs @@ -91,7 +91,7 @@ impl NodeIntegrationCtxBuilder { pub async fn new() -> Self { let tmpdir = tempfile::tempdir().unwrap(); let bus = SharedMessageBus::new(BusMetrics::global("default".to_string())); - let crypto = BlstCrypto::new("test".to_owned()).unwrap(); + let crypto = BlstCrypto::new("test").unwrap(); let mut conf = Conf::new( None, tmpdir.path().to_str().map(|s| s.to_owned()), diff --git a/tests/fixtures/test_helpers.rs b/tests/fixtures/test_helpers.rs index fb201935..fb4d536c 100644 --- a/tests/fixtures/test_helpers.rs +++ b/tests/fixtures/test_helpers.rs @@ -5,7 +5,10 @@ use client_sdk::transaction_builder::{ProvableBlobTx, StateUpdater, TxExecutor}; use hyle::{ model::BlobTransaction, rest::client::NodeApiHttpClient, - utils::conf::{Conf, Consensus}, + utils::{ + conf::{Conf, Consensus}, + crypto::BlstCrypto, + }, }; use hyle_model::TxHash; use rand::Rng; @@ -108,6 +111,10 @@ impl TestProcess { ron::ser::to_writer(std::fs::File::create(&conf_file).unwrap(), &conf).unwrap(); cmd.env("RISC0_DEV_MODE", "1"); + + let secret = BlstCrypto::secret_from_name(&conf.id); + cmd.env("HYLE_VALIDATOR_SECRET", hex::encode(secret)); + Self { conf, dir: tmpdir,