rock_n_rollup/plugins/
crypto.rs1use base58::{FromBase58, ToBase58};
2use sha2::{Digest, Sha256};
3
4use crate::core::Runtime;
5use crate::plugins::hasher::Hasher;
6
7fn from_base58(prefix_size: usize, encoded: &str) -> Result<Vec<u8>, ()> {
10 let check_sum_size = 4;
11 let decoded = encoded.from_base58().map_err(|_| ())?;
12 let _payload = &decoded[..decoded.len() - check_sum_size]; let bytes = decoded[prefix_size..].to_vec();
14 let bytes = bytes[..bytes.len() - check_sum_size].to_vec();
15 Ok(bytes)
16}
17
18fn to_base58(prefix: Vec<u8>, data: &[u8]) -> String {
20 let mut result = prefix;
21 result.extend(data);
22 let checksum = Sha256::digest(&Sha256::digest(&result)).to_vec()[..4].to_vec();
23 result.extend(checksum);
24 result.to_base58()
25}
26
27#[derive(Clone)]
28pub enum PublicKey {
29 Ed25519(ed25519_compact::PublicKey),
31}
32
33#[derive(Clone)]
34pub enum Signature {
35 Ed25519(ed25519_compact::Signature),
36}
37
38impl TryFrom<String> for PublicKey {
39 type Error = ();
40
41 fn try_from(value: String) -> Result<Self, Self::Error> {
42 let public_key = from_base58(4, &value)?;
43 let ed25519 = ed25519_compact::PublicKey::from_slice(&public_key).map_err(|_| ())?;
44 Ok(PublicKey::Ed25519(ed25519))
45 }
46}
47
48impl ToString for PublicKey {
49 fn to_string(&self) -> String {
50 match self {
51 PublicKey::Ed25519(ed25519) => {
52 let bytes = ed25519.as_ref();
53
54 to_base58(vec![13, 15, 37, 217], bytes)
55 }
56 }
57 }
58}
59
60impl TryFrom<String> for Signature {
61 type Error = ();
62 fn try_from(value: String) -> Result<Self, Self::Error> {
63 let signature = from_base58(5, &value)?;
64 let sig = ed25519_compact::Signature::from_slice(&signature).map_err(|_| ())?;
65 Ok(Signature::Ed25519(sig))
66 }
67}
68
69pub trait Verifier {
70 fn verify_signature(
75 &mut self,
76 signature: &Signature,
77 public_key: &PublicKey,
78 data: &[u8],
79 ) -> bool;
80}
81
82impl<R> Verifier for R
83where
84 R: Runtime + Hasher,
85{
86 fn verify_signature(
87 &mut self,
88 signature: &Signature,
89 public_key: &PublicKey,
90 data: &[u8],
91 ) -> bool {
92 let data = self.hash(data);
93
94 match (signature, public_key) {
95 (Signature::Ed25519(sig), PublicKey::Ed25519(pkey)) => {
96 let res = pkey.verify(data, sig);
97 res.is_ok()
98 }
99 }
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::{PublicKey, Signature, Verifier};
106 use crate::core::MockRuntime;
107
108 #[test]
109 fn test_ed25519_pkey_deserialization() {
110 let string = "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK".to_string();
111 let pkey = PublicKey::try_from(string);
112
113 assert!(pkey.is_ok())
114 }
115
116 #[test]
117 fn test_ed25519_pkey_serialization() {
118 let string = "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK".to_string();
119 let pkey = PublicKey::try_from(string.clone()).unwrap().to_string();
120
121 assert_eq!(string, pkey);
122 }
123
124 #[test]
125 fn test_ed25519_signature_deserialization() {
126 let encoded = "edsigtuU5nUqBniorqTFXFixkG6ZkfvEPrfc9aT9DnMAeims2AX2yjpgYaedXBoKzAGHE3ZXSi1hZz6piZ3itTE7f2F4FoaxXtM";
127 let signature = Signature::try_from(encoded.to_string());
128
129 assert!(signature.is_ok())
130 }
131
132 #[test]
133 fn test_verify_ed25519_signature() {
134 let mut rt = MockRuntime::default();
135
136 let encoded = "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK";
137 let public_key = PublicKey::try_from(encoded.to_string()).unwrap();
138
139 let encoded = "edsigtuU5nUqBniorqTFXFixkG6ZkfvEPrfc9aT9DnMAeims2AX2yjpgYaedXBoKzAGHE3ZXSi1hZz6piZ3itTE7f2F4FoaxXtM";
141 let signature = Signature::try_from(encoded.to_string()).unwrap();
142
143 let data = "hello world".as_bytes();
145
146 let is_ok = rt.verify_signature(&signature, &public_key, data);
147
148 assert!(is_ok);
149 }
150}