From 84bb5a385eb87c9ae9567dce03fee17844a1ab97 Mon Sep 17 00:00:00 2001 From: Cesar Rodas Date: Thu, 21 Dec 2023 17:01:20 -0300 Subject: [PATCH] Add recover-public-key to forc-crypto This function is ported from https://github.com/FuelLabs/forc-wallet/pull/152 --- forc-plugins/forc-crypto/src/args.rs | 19 +++++---- .../forc-crypto/src/{keygen => keys}/mod.rs | 1 + .../src/{keygen => keys}/new_key.rs | 2 - .../src/{keygen => keys}/parse_secret.rs | 2 - forc-plugins/forc-crypto/src/keys/recover.rs | 42 +++++++++++++++++++ forc-plugins/forc-crypto/src/main.rs | 19 +++++---- 6 files changed, 65 insertions(+), 20 deletions(-) rename forc-plugins/forc-crypto/src/{keygen => keys}/mod.rs (95%) rename forc-plugins/forc-crypto/src/{keygen => keys}/new_key.rs (95%) rename forc-plugins/forc-crypto/src/{keygen => keys}/parse_secret.rs (95%) create mode 100644 forc-plugins/forc-crypto/src/keys/recover.rs diff --git a/forc-plugins/forc-crypto/src/args.rs b/forc-plugins/forc-crypto/src/args.rs index 233e86f7c62..7fed8bb391b 100644 --- a/forc-plugins/forc-crypto/src/args.rs +++ b/forc-plugins/forc-crypto/src/args.rs @@ -86,16 +86,19 @@ fn read_as_binary(content: &Option) -> Vec { /// fully valid hex strings are accepted. /// 7. Any other string, or any malformed hex string will be treated as a /// vector of bytes +pub fn read_content_or_filepath(arg: Option) -> Vec { + match checked_read_file(&arg) { + Some(bytes) => bytes, + None => match checked_read_stdin(&arg, io::stdin().lock()) { + Some(bytes) => bytes, + None => read_as_binary(&arg), + }, + } +} + impl From for Vec { fn from(value: HashArgs) -> Self { - let arg = value.content_or_filepath; - match checked_read_file(&arg) { - Some(bytes) => bytes, - None => match checked_read_stdin(&arg, io::stdin().lock()) { - Some(bytes) => bytes, - None => read_as_binary(&arg), - }, - } + read_content_or_filepath(value.content_or_filepath) } } diff --git a/forc-plugins/forc-crypto/src/keygen/mod.rs b/forc-plugins/forc-crypto/src/keys/mod.rs similarity index 95% rename from forc-plugins/forc-crypto/src/keygen/mod.rs rename to forc-plugins/forc-crypto/src/keys/mod.rs index 6958367dc3d..90b4de3cc5a 100644 --- a/forc-plugins/forc-crypto/src/keygen/mod.rs +++ b/forc-plugins/forc-crypto/src/keys/mod.rs @@ -2,6 +2,7 @@ use clap::ValueEnum; pub mod new_key; pub mod parse_secret; +pub mod recover; #[derive(Clone, Debug, Default, ValueEnum)] pub enum KeyType { diff --git a/forc-plugins/forc-crypto/src/keygen/new_key.rs b/forc-plugins/forc-crypto/src/keys/new_key.rs similarity index 95% rename from forc-plugins/forc-crypto/src/keygen/new_key.rs rename to forc-plugins/forc-crypto/src/keys/new_key.rs index d84ff450eb2..449ee8884f5 100644 --- a/forc-plugins/forc-crypto/src/keygen/new_key.rs +++ b/forc-plugins/forc-crypto/src/keys/new_key.rs @@ -1,5 +1,3 @@ -//! This file will be hosted here until -//! https://github.com/FuelLabs/sway/issues/5170 is fixed use super::KeyType; use anyhow::Result; use fuel_core_types::{ diff --git a/forc-plugins/forc-crypto/src/keygen/parse_secret.rs b/forc-plugins/forc-crypto/src/keys/parse_secret.rs similarity index 95% rename from forc-plugins/forc-crypto/src/keygen/parse_secret.rs rename to forc-plugins/forc-crypto/src/keys/parse_secret.rs index 309af4fae2a..82f2cbf8c1b 100644 --- a/forc-plugins/forc-crypto/src/keygen/parse_secret.rs +++ b/forc-plugins/forc-crypto/src/keys/parse_secret.rs @@ -1,5 +1,3 @@ -//! This file will be hosted here until -//! https://github.com/FuelLabs/sway/issues/5170 is fixed use super::KeyType; use anyhow::Result; use fuel_core_types::{fuel_crypto::SecretKey, fuel_tx::Input}; diff --git a/forc-plugins/forc-crypto/src/keys/recover.rs b/forc-plugins/forc-crypto/src/keys/recover.rs new file mode 100644 index 00000000000..65e8d653505 --- /dev/null +++ b/forc-plugins/forc-crypto/src/keys/recover.rs @@ -0,0 +1,42 @@ +use crate::args::read_content_or_filepath; +use anyhow::Result; +use fuel_crypto::{fuel_types::Address, Message, Signature}; +use fuels_core::types::bech32::Bech32Address; +use serde_json::json; + +forc_util::cli_examples! { + [ Recovers a public key from a message and its signature => crypto r#"recover-public-key \ + 0xb0b2f29b52d95c1cba47ea7c7edeec6c84a0bd196df489e219f6f388b69d760479b994f4bae2d5f2abef7d5faf7d9f5ee3ea47ada4d15b7a7ee2777dcd7b36bb \ + "Blah blah blah""#] +} + +/// Parse a secret key to view the associated public key +#[derive(Debug, clap::Args)] +#[clap( + author, + version, + about = "Recovers a public key from a message and its signature", + after_long_help = help(), +)] +pub struct Arg { + /// A private key in hex format + signature: Signature, + /// A message + message: Option, +} + +pub fn handler(arg: Arg) -> Result { + let message = Message::new(read_content_or_filepath(arg.message)); + let public_key = Signature::recover(&arg.signature, &message)?; + + let bytes = *public_key.hash(); + + let bech32 = Bech32Address::from(Address::from(bytes)); + let addr = Address::from(bytes); + + Ok(json!({ + "PublicKey": public_key.to_string(), + "Bench32": bech32.to_string(), + "Address": addr.to_string(), + })) +} diff --git a/forc-plugins/forc-crypto/src/main.rs b/forc-plugins/forc-crypto/src/main.rs index 9a3dd4f3858..79adb613ad5 100644 --- a/forc-plugins/forc-crypto/src/main.rs +++ b/forc-plugins/forc-crypto/src/main.rs @@ -13,7 +13,7 @@ use termion::screen::IntoAlternateScreen; mod address; mod args; mod keccak256; -mod keygen; +mod keys; mod sha256; const ABOUT: &str = "Forc plugin for hashing arbitrary data."; @@ -21,11 +21,12 @@ const ABOUT: &str = "Forc plugin for hashing arbitrary data."; fn help() -> &'static str { Box::leak( format!( - "EXAMPLES:\n{}{}{}{}", + "EXAMPLES:\n{}{}{}{}{}", args::examples(), address::examples(), - keygen::new_key::examples(), - keygen::parse_secret::examples(), + keys::new_key::examples(), + keys::parse_secret::examples(), + keys::recover::examples(), ) .into_boxed_str(), ) @@ -42,8 +43,9 @@ pub enum Command { Keccak256(args::HashArgs), Sha256(args::HashArgs), Address(address::Args), - NewKey(keygen::new_key::Arg), - ParseSecret(keygen::parse_secret::Arg), + RecoverPublicKey(keys::recover::Arg), + NewKey(keys::new_key::Arg), + ParseSecret(keys::parse_secret::Arg), } fn main() { @@ -58,10 +60,11 @@ fn run() -> Result<()> { let app = Command::parse(); let content = match app { Command::Keccak256(arg) => keccak256::hash(arg)?, + Command::RecoverPublicKey(arg) => keys::recover::handler(arg)?, Command::Sha256(arg) => sha256::hash(arg)?, Command::Address(arg) => address::dump_address(arg.address)?, - Command::NewKey(arg) => keygen::new_key::handler(arg)?, - Command::ParseSecret(arg) => keygen::parse_secret::handler(arg)?, + Command::NewKey(arg) => keys::new_key::handler(arg)?, + Command::ParseSecret(arg) => keys::parse_secret::handler(arg)?, }; display_output(content)