forc_crypto/keys/
get_public_key.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use crate::args::read_content_filepath_or_stdin;
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! {
    crate::Command {
        [ Get the public key from a message and its signature => r#"forc crypto get-public-key \
            0x1eff08081394b72239a0cf7ff6b499213dcb7a338bedbd75d072d504588ef27a1f74d5ceb2f111ec02ede097fb09ed00aa9867922ed39299dae0b1afc0fa8661 \
            "This is a message that is signed""# ]
    }
}

/// Parse a secret key to view the associated public key
#[derive(Debug, clap::Args)]
#[clap(
    author,
    version,
    about = "Get the 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<String>,
}

pub fn handler(arg: Arg) -> Result<serde_json::Value> {
    let message = Message::new(read_content_filepath_or_stdin(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(),
        "Bech32": bech32.to_string(),
        "Address": addr.to_string(),
    }))
}

#[cfg(test)]
mod test {
    use std::str::FromStr;

    use super::*;

    #[test]
    fn expect_output() {
        let arg = Arg {
            signature: Signature::from_str("0x1eff08081394b72239a0cf7ff6b499213dcb7a338bedbd75d072d504588ef27a1f74d5ceb2f111ec02ede097fb09ed00aa9867922ed39299dae0b1afc0fa8661").unwrap(),
            message: Some("This is a message that is signed".to_string()),
        };
        let json = handler(arg).unwrap();
        assert_eq!(
            "fuel1fmmfhjapeak3knq96arrvttwrtmzghe0w9gx79gkcl2jhaweakdqfqhzdr",
            json.as_object()
                .unwrap()
                .get("Bech32")
                .unwrap()
                .as_str()
                .unwrap(),
        )
    }
}