Skip to content

Commit 0f12044

Browse files
authored
Merge pull request #648 from openmina/fix/configure-keypair
Fix configure keypair
2 parents 9e573ce + 13799c1 commit 0f12044

File tree

4 files changed

+49
-26
lines changed

4 files changed

+49
-26
lines changed

cli/src/commands/node/mod.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ pub struct Node {
2828
#[arg(long)]
2929
pub libp2p_keypair: Option<String>,
3030

31+
// warning, this overrides `OPENMINA_P2P_SEC_KEY`
32+
/// Compatibility with OCaml Mina node
33+
#[arg(env = "MINA_LIBP2P_PASS")]
34+
pub libp2p_password: Option<String>,
35+
3136
/// Http port to listen on
3237
#[arg(long, short, env, default_value = "3000")]
3338
pub port: u16,
@@ -70,6 +75,8 @@ pub struct Node {
7075
/// MINA_PRIVKEY_PASS must be set to decrypt the keyfile
7176
#[arg(long, env)]
7277
pub producer_key: Option<PathBuf>,
78+
#[arg(env = "MINA_PRIVKEY_PASS")]
79+
pub producer_key_password: Option<String>,
7380
/// Snark fee, in Mina
7481
#[arg(long, env, default_value_t = 1_000_000)]
7582
pub snarker_fee: u64,
@@ -131,10 +138,8 @@ impl Node {
131138
}
132139

133140
// warning, this overrides `OPENMINA_P2P_SEC_KEY`
134-
if let Some(key_file) = self.libp2p_keypair {
135-
use openmina_node_account::AccountSecretKey;
136-
137-
match AccountSecretKey::from_encrypted_file(&key_file) {
141+
if let (Some(key_file), Some(password)) = (&self.libp2p_keypair, &self.libp2p_password) {
142+
match AccountSecretKey::from_encrypted_file(key_file, password) {
138143
Ok(sk) => {
139144
node_builder.p2p_sec_key(SecretKey::from_bytes(sk.to_bytes()));
140145
node::core::info!(
@@ -151,8 +156,16 @@ impl Node {
151156
file_name = key_file,
152157
err = err.to_string(),
153158
);
159+
return Err(err.into());
154160
}
155161
}
162+
} else if self.libp2p_keypair.is_some() && self.libp2p_password.is_none() {
163+
let error = "keyfile is specified, but `MINA_LIBP2P_PASS` is not set";
164+
node::core::error!(
165+
node::core::log::system_time();
166+
summary = error,
167+
);
168+
return Err(anyhow::anyhow!(error));
156169
}
157170

158171
node_builder.p2p_libp2p_port(self.libp2p_port);
@@ -169,11 +182,13 @@ impl Node {
169182
node_builder.initial_peers_from_url(url)?;
170183
}
171184

172-
if let Some(producer_key_path) = self.producer_key {
185+
if let (Some(producer_key_path), Some(pasword)) =
186+
(self.producer_key, &self.producer_key_password)
187+
{
173188
node::core::info!(node::core::log::system_time(); summary = "loading provers index");
174189
ledger::proofs::gates::get_provers();
175190
node::core::info!(node::core::log::system_time(); summary = "loaded provers index");
176-
node_builder.block_producer_from_file(producer_key_path)?;
191+
node_builder.block_producer_from_file(producer_key_path, pasword)?;
177192
}
178193

179194
if let Some(sec_key) = self.run_snarker {

node/account/src/secret_key.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{env, fmt, fs, path::Path, str::FromStr};
1+
use std::{fmt, fs, path::Path, str::FromStr};
22

33
use argon2::{password_hash::SaltString, Argon2, Params, PasswordHasher};
44
use base64::Engine;
@@ -73,19 +73,26 @@ impl AccountSecretKey {
7373
self.0.public.clone().into_compressed()
7474
}
7575

76-
pub fn from_encrypted_file(path: impl AsRef<Path>) -> Result<Self, EncryptionError> {
76+
pub fn from_encrypted_file(
77+
path: impl AsRef<Path>,
78+
password: &str,
79+
) -> Result<Self, EncryptionError> {
7780
let key_file = fs::File::open(path)?;
7881
let encrypted: EncryptedSecretKey = serde_json::from_reader(key_file)?;
79-
encrypted.try_decrypt()
82+
encrypted.try_decrypt(password)
8083
}
8184

82-
pub fn to_encrypted_file(&self, path: impl AsRef<Path>) -> Result<(), EncryptionError> {
85+
pub fn to_encrypted_file(
86+
&self,
87+
path: impl AsRef<Path>,
88+
password: &str,
89+
) -> Result<(), EncryptionError> {
8390
if path.as_ref().exists() {
8491
panic!("File {} already exists", path.as_ref().display())
8592
}
8693

8794
let f = fs::File::create(path)?;
88-
let encrypted = EncryptedSecretKey::encrypt(&self.to_bytes())?;
95+
let encrypted = EncryptedSecretKey::encrypt(&self.to_bytes(), password)?;
8996

9097
serde_json::to_writer(f, &encrypted)?;
9198
Ok(())
@@ -188,8 +195,6 @@ pub enum EncryptionError {
188195
Io(#[from] std::io::Error),
189196
#[error(transparent)]
190197
SerdeJson(#[from] serde_json::Error),
191-
#[error("MINA_PRIVKEY_PASS environment variable must be set!")]
192-
PasswordEnvVarMissing,
193198
}
194199

195200
#[derive(Serialize, Deserialize, Debug)]
@@ -222,10 +227,8 @@ impl EncryptedSecretKey {
222227
))
223228
}
224229

225-
pub fn try_decrypt(&self) -> Result<AccountSecretKey, EncryptionError> {
230+
pub fn try_decrypt(&self, password: &str) -> Result<AccountSecretKey, EncryptionError> {
226231
// prepare inputs to cipher
227-
let password =
228-
env::var("MINA_PRIVKEY_PASS").map_err(|_| EncryptionError::PasswordEnvVarMissing)?;
229232
let password = password.as_bytes();
230233
let pwsalt = self.pwsalt.try_decode(Self::ENCRYPTION_DATA_VERSION_BYTE)?;
231234
let nonce = self.nonce.try_decode(Self::ENCRYPTION_DATA_VERSION_BYTE)?;
@@ -253,14 +256,12 @@ impl EncryptedSecretKey {
253256
Ok(AccountSecretKey::from_bytes(&decrypted[1..])?)
254257
}
255258

256-
pub fn encrypt(key: &[u8]) -> Result<Self, EncryptionError> {
259+
pub fn encrypt(key: &[u8], password: &str) -> Result<Self, EncryptionError> {
257260
let argon2 = Self::setup_argon(Self::PW_DIFF)?;
258261

259262
// add the prefix byt to the key
260263
let mut key_prefixed = vec![Self::SECRET_KEY_PREFIX_BYTE];
261264
key_prefixed.extend(key);
262-
let password =
263-
env::var("MINA_PRIVKEY_PASS").map_err(|_| EncryptionError::PasswordEnvVarMissing)?;
264265

265266
let salt = SaltString::generate(&mut OsRng);
266267
let password_hash = argon2
@@ -290,6 +291,8 @@ impl EncryptedSecretKey {
290291

291292
#[cfg(test)]
292293
mod tests {
294+
use std::env;
295+
293296
use super::*;
294297

295298
#[test]
@@ -316,18 +319,19 @@ mod tests {
316319

317320
#[test]
318321
fn test_encrypt_decrypt() {
319-
env::set_var("MINA_PRIVKEY_PASS", "not-very-secure-pass");
322+
let password = "not-very-secure-pass";
323+
320324
let new_key = AccountSecretKey::rand();
321325
let tmp_dir = env::temp_dir();
322326
let tmp_path = format!("{}/{}-key", tmp_dir.display(), new_key.public_key());
323327

324328
// dump encrypted file
325329
new_key
326-
.to_encrypted_file(&tmp_path)
330+
.to_encrypted_file(&tmp_path, password)
327331
.expect("Failed to encrypt secret key");
328332

329333
// load and decrypt
330-
let decrypted = AccountSecretKey::from_encrypted_file(&tmp_path)
334+
let decrypted = AccountSecretKey::from_encrypted_file(&tmp_path, password)
331335
.expect("Failed to decrypt secret key file");
332336

333337
assert_eq!(
@@ -339,10 +343,10 @@ mod tests {
339343

340344
#[test]
341345
fn test_ocaml_key_decrypt() {
342-
env::set_var("MINA_PRIVKEY_PASS", "not-very-secure-pass");
346+
let password = "not-very-secure-pass";
343347
let key_path = "../tests/files/accounts/test-key-1";
344348
let expected_public_key = "B62qmg7n4XqU3SFwx9KD9B7gxsKwxJP5GmxtBpHp1uxyN3grujii9a1";
345-
let decrypted = AccountSecretKey::from_encrypted_file(key_path)
349+
let decrypted = AccountSecretKey::from_encrypted_file(key_path, password)
346350
.expect("Failed to decrypt secret key file");
347351

348352
assert_eq!(

node/native/src/node/builder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,9 @@ impl NodeBuilder {
180180
pub fn block_producer_from_file(
181181
&mut self,
182182
path: impl AsRef<Path>,
183+
password: &str,
183184
) -> anyhow::Result<&mut Self> {
184-
let key = AccountSecretKey::from_encrypted_file(path)
185+
let key = AccountSecretKey::from_encrypted_file(path, password)
185186
.context("Failed to decrypt secret key file")?;
186187
Ok(self.block_producer(key))
187188
}

producer-dashboard/src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ async fn main() {
4141
let db = Database::open(config.database_path).expect("Failed to open Database");
4242
println!("[main] DB opened");
4343

44-
let key = AccountSecretKey::from_encrypted_file(config.private_key_path)
44+
let password = std::env::var("MINA_PRIVKEY_PASS")
45+
.expect("Expected password in the variable `MINA_PRIVKEY_PASS`");
46+
47+
let key = AccountSecretKey::from_encrypted_file(config.private_key_path, &password)
4548
.expect("failed to decrypt secret key file");
4649
println!("[main] Producer key loaded");
4750

0 commit comments

Comments
 (0)