arkecosystem_crypto/utils/
message.rs

1use hex;
2use secp256k1;
3use secp256k1::{Secp256k1, Signature};
4use serde_json;
5use serde_json::Value;
6use sha2::{Digest, Sha256};
7
8use super::super::identities::{private_key, public_key};
9
10#[derive(Clone, Debug, Deserialize, Serialize)]
11pub struct Message {
12    #[serde(rename = "publickey")]
13    pub public_key: String,
14    pub signature: String,
15    pub message: String,
16}
17
18impl Message {
19    pub fn new(public_key: &str, signature: &str, message: &str) -> Message {
20        Message {
21            public_key: public_key.to_owned(),
22            signature: signature.to_owned(),
23            message: message.to_owned(),
24        }
25    }
26
27    pub fn sign(message: &str, passphrase: &str) -> Message {
28        let key = private_key::from_passphrase(passphrase).unwrap();
29        let public_key = public_key::from_private_key(&key);
30
31        Message {
32            public_key: hex::encode(&public_key.serialize()[..]),
33            signature: private_key::sign(message.as_bytes(), passphrase),
34            message: message.to_owned(),
35        }
36    }
37
38    // TODO: unwrap
39    pub fn verify(&self) -> bool {
40        let hash = Sha256::digest_str(&self.message);
41
42        let message = secp256k1::Message::from_slice(&hash);
43        if message.is_err() {
44            return false;
45        }
46
47        let decoded = hex::decode(&self.signature);
48        if decoded.is_err() {
49            return false;
50        }
51
52        let secp = Secp256k1::new();
53        let signature = Signature::from_der(&secp, &decoded.unwrap());
54        if signature.is_err() {
55            return false;
56        }
57
58        let pk = public_key::from_hex(&self.public_key).unwrap();
59        secp.verify(&message.unwrap(), &signature.unwrap(), &pk)
60            .is_ok()
61    }
62
63    pub fn to_json(&self) -> Result<String, serde_json::Error> {
64        serde_json::to_string(&self)
65    }
66
67    pub fn to_map(&self) -> Result<Value, serde_json::Error> {
68        serde_json::to_value(&self)
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn test_verify() {
78        let m = Message::new(
79                "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
80                "304402200fb4adddd1f1d652b544ea6ab62828a0a65b712ed447e2538db0caebfa68929e02205ecb2e1c63b29879c2ecf1255db506d671c8b3fa6017f67cfd1bf07e6edd1cc8",
81                "Hello World"
82            );
83
84        assert!(m.verify());
85    }
86
87    #[test]
88    fn test_sign() {
89        let sig = Message::sign("Hello World", "this is a top secret passphrase");
90        assert_eq!(sig.signature, "304402200fb4adddd1f1d652b544ea6ab62828a0a65b712ed447e2538db0caebfa68929e02205ecb2e1c63b29879c2ecf1255db506d671c8b3fa6017f67cfd1bf07e6edd1cc8");
91    }
92
93}