From 1c738d5aa977acfb610b5ff017f20b9f680879d6 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Fri, 10 Nov 2023 16:03:56 +0100 Subject: [PATCH 1/2] Add `to_hex` and `from_hex` on `Secp256k1PrivateKey`, validation of private key when using cmd_set_default_account, throwing specific error if you accidentally pass in the public key instead of private key. --- simulator/src/resim/cmd_new_account.rs | 2 +- .../src/resim/cmd_set_default_account.rs | 11 ++++++++-- simulator/src/resim/config.rs | 2 +- simulator/src/resim/error.rs | 3 +++ simulator/src/resim/mod.rs | 21 +++++++++++-------- .../src/signing/secp256k1/private_key.rs | 10 +++++++++ 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/simulator/src/resim/cmd_new_account.rs b/simulator/src/resim/cmd_new_account.rs index 0dc9800e69b..2a49622591f 100644 --- a/simulator/src/resim/cmd_new_account.rs +++ b/simulator/src/resim/cmd_new_account.rs @@ -124,7 +124,7 @@ impl NewAccount { || configs.default_owner_badge.is_none() { configs.default_account = Some(account); - configs.default_private_key = Some(hex::encode(private_key.to_bytes())); + configs.default_private_key = Some(private_key.to_hex()); configs.default_owner_badge = Some(owner_badge); set_configs(&configs)?; diff --git a/simulator/src/resim/cmd_set_default_account.rs b/simulator/src/resim/cmd_set_default_account.rs index e2ddd5a1586..dcc5874447c 100644 --- a/simulator/src/resim/cmd_set_default_account.rs +++ b/simulator/src/resim/cmd_set_default_account.rs @@ -19,12 +19,19 @@ pub struct SetDefaultAccount { impl SetDefaultAccount { pub fn run(&self, out: &mut O) -> Result<(), Error> { let mut configs = get_configs()?; + let private_key = parse_private_key_from_str(&self.private_key).map_err(|e| { + if Secp256k1PublicKey::from_str(&self.private_key).is_ok() { + Error::GotPublicKeyExpectedPrivateKey + } else { + e + } + })?; configs.default_account = Some(self.component_address.0); - configs.default_private_key = Some(self.private_key.clone()); + configs.default_private_key = Some(private_key.to_hex()); configs.default_owner_badge = Some(self.owner_badge.clone().0); set_configs(&configs)?; writeln!(out, "Default account updated!").map_err(Error::IOError)?; Ok(()) } -} +} \ No newline at end of file diff --git a/simulator/src/resim/config.rs b/simulator/src/resim/config.rs index ef0007160de..df29ce3a1da 100644 --- a/simulator/src/resim/config.rs +++ b/simulator/src/resim/config.rs @@ -59,7 +59,7 @@ pub fn get_default_account() -> Result { pub fn get_default_private_key() -> Result { get_configs()? .default_private_key - .map(|v| Secp256k1PrivateKey::from_bytes(&hex::decode(&v).unwrap()).unwrap()) + .map(|v| Secp256k1PrivateKey::from_hex(&v).unwrap()) .ok_or(Error::NoDefaultPrivateKey) } diff --git a/simulator/src/resim/error.rs b/simulator/src/resim/error.rs index 8fbc0a16ec5..ac1f567a2b8 100644 --- a/simulator/src/resim/error.rs +++ b/simulator/src/resim/error.rs @@ -67,6 +67,9 @@ pub enum Error { InvalidPrivateKey, + /// e.g. if you accidentally pass in a public key in `set_default_account` command. + GotPublicKeyExpectedPrivateKey, + NonFungibleGlobalIdError(ParseNonFungibleGlobalIdError), FailedToBuildArguments(BuildCallArgumentError), diff --git a/simulator/src/resim/mod.rs b/simulator/src/resim/mod.rs index aa6a6e4f9f7..53e541e3828 100644 --- a/simulator/src/resim/mod.rs +++ b/simulator/src/resim/mod.rs @@ -318,19 +318,22 @@ pub fn process_receipt(receipt: TransactionReceipt) -> Result Result { + Secp256k1PrivateKey::from_bytes(slice).map_err(|_| Error::InvalidPrivateKey) +} + +pub fn parse_private_key_from_str(key: &str) -> Result { + hex::decode(key) + .map_err(|_| Error::InvalidPrivateKey) + .and_then(|bytes| parse_private_key_from_bytes(&bytes)) +} + pub fn get_signing_keys(signing_keys: &Option) -> Result, Error> { let private_keys = if let Some(keys) = signing_keys { keys.split(",") .map(str::trim) - .filter(|s| !s.is_empty()) - .map(|key| { - hex::decode(key) - .map_err(|_| Error::InvalidPrivateKey) - .and_then(|bytes| { - Secp256k1PrivateKey::from_bytes(&bytes) - .map_err(|_| Error::InvalidPrivateKey) - }) - }) + .filter(|s: &&str| !s.is_empty()) + .map(parse_private_key_from_str) .collect::, Error>>()? } else { vec![get_default_private_key()?] diff --git a/transaction/src/signing/secp256k1/private_key.rs b/transaction/src/signing/secp256k1/private_key.rs index 566105020e9..2466afd7d13 100644 --- a/transaction/src/signing/secp256k1/private_key.rs +++ b/transaction/src/signing/secp256k1/private_key.rs @@ -27,6 +27,16 @@ impl Secp256k1PrivateKey { self.0.secret_bytes().to_vec() } + pub fn to_hex(&self) -> String { + hex::encode(self.to_bytes()) + } + + pub fn from_hex(s: &str) -> Result { + hex::decode(s) + .map_err(|_| ()) + .and_then(|v| Self::from_bytes(&v)) + } + pub fn from_bytes(slice: &[u8]) -> Result { if slice.len() != Secp256k1PrivateKey::LENGTH { return Err(()); From 4d9167dfec86913c909dd53948e0c24006baa5a0 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Fri, 10 Nov 2023 16:31:34 +0100 Subject: [PATCH 2/2] add unit test --- .../src/resim/cmd_set_default_account.rs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/simulator/src/resim/cmd_set_default_account.rs b/simulator/src/resim/cmd_set_default_account.rs index dcc5874447c..e8fa6315d35 100644 --- a/simulator/src/resim/cmd_set_default_account.rs +++ b/simulator/src/resim/cmd_set_default_account.rs @@ -34,4 +34,32 @@ impl SetDefaultAccount { writeln!(out, "Default account updated!").map_err(Error::IOError)?; Ok(()) } -} \ No newline at end of file +} + +#[cfg(test)] +#[test] +fn test_validation() { + let mut out = std::io::stdout(); + let private_key = Secp256k1PrivateKey::from_hex( + "6847c11e2d602548dbf38789e0a1f4543c1e7719e4f591d4aa6e5684f5c13d9c", + ) + .unwrap(); + let public_key = private_key.public_key().to_string(); + + let make_cmd = |key_string: String| { + return SetDefaultAccount { + component_address: SimulatorComponentAddress::from_str( + "account_sim1c9yeaya6pehau0fn7vgavuggeev64gahsh05dauae2uu25njk224xz", + ) + .unwrap(), + private_key: key_string, + owner_badge: SimulatorNonFungibleGlobalId::from_str( + "resource_sim1ngvrads4uj3rgq2v9s78fzhvry05dw95wzf3p9r8skhqusf44dlvmr:#1#", + ) + .unwrap(), + }; + }; + + assert!(make_cmd(private_key.to_hex()).run(&mut out).is_ok()); + assert!(make_cmd(public_key.to_string()).run(&mut out).is_err()); +}