verify_keplr_sign/
lib.rs

1use ecdsa::signature::DigestVerifier;
2use k256::sha2::{Digest, Sha256};
3use serde::{Deserialize, Serialize};
4use std::str::FromStr;
5
6#[derive(Serialize, Deserialize)]
7pub struct PublicKey {
8    #[serde(rename = "type")]
9    pub sig_type: String,
10    #[serde(rename = "value")]
11    pub sig_value: String,
12}
13
14#[derive(Serialize, Deserialize)]
15pub struct Signature {
16    pub pub_key: PublicKey,
17    pub signature: String,
18}
19
20fn generate_amino_transaction_string(signer: &str, data: &str) -> String {
21    format!("{{\"account_number\":\"0\",\"chain_id\":\"\",\"fee\":{{\"amount\":[],\"gas\":\"0\"}},\"memo\":\"\",\"msgs\":[{{\"type\":\"sign/MsgSignData\",\"value\":{{\"data\":\"{}\",\"signer\":\"{}\"}}}}],\"sequence\":\"0\"}}", data, signer)
22}
23
24pub fn verify_arbitrary(
25    account_addr: &str,
26    pubkey: &str,
27    data: &[u8],
28    signature: &Signature,
29) -> bool {
30    let rpc_signature_to_compare = hex::encode(base64::decode(&signature.signature).unwrap());
31    let signature: k256::ecdsa::Signature =
32        ecdsa::Signature::from_str(&rpc_signature_to_compare).unwrap();
33
34    let digest = Sha256::new_with_prefix(generate_amino_transaction_string(
35        account_addr,
36        &base64::encode(data),
37    ));
38
39    let pk = tendermint::PublicKey::from_raw_secp256k1(base64::decode(pubkey).unwrap().as_slice())
40        .unwrap();
41    let vk = pk.secp256k1().unwrap();
42
43    let verification = vk.verify_digest(digest, &signature);
44
45    verification.is_ok()
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    fn get_signature() -> Signature {
53        Signature {
54            pub_key: PublicKey {
55                sig_type: String::from("tendermint/PubKeySecp256k1"),
56                sig_value: String::from("Avt8e5UqfoRAh0RBUzHCu9arv7UFEFdfcv657h6TtSZE"),
57            },
58            signature: String::from("9PrDYrTb1tv/TALC/lgRIIekfwNMBPOra0QpaAqNCbADXT8vR9n0SS7L2OSaXma3UMrOLGTbWlLDImNhcZVgzA==")
59        }
60    }
61
62    #[test]
63    fn it_verifies_signature() {
64        let signature = get_signature();
65
66        assert_eq!(
67            true,
68            verify_arbitrary(
69                "juno105asxv7pt0fzxlz642pf4svm29u39zxzdq2ad5",
70                "Avt8e5UqfoRAh0RBUzHCu9arv7UFEFdfcv657h6TtSZE",
71                b"test",
72                &signature
73            )
74        );
75    }
76
77    #[test]
78    fn it_doesnt_verifies_signature() {
79        let signature = get_signature();
80
81        assert_eq!(
82            false,
83            verify_arbitrary(
84                "juno105asxv7pt0fzxlz642pf4svm29u39zxzdq2ad5",
85                "Avt8e5UqfoRAh0RBUzHCu9arv7UFEFdfcv657h6TtSZE",
86                b"not test",
87                &signature
88            )
89        );
90    }
91}