|
@@ -1,39 +1,128 @@
|
|
1
|
+#[macro_use]
|
|
2
|
+mod serde_impl {
|
|
3
|
+ macro_rules! serde_impl {
|
|
4
|
+ ($key_type: ty) => {
|
|
5
|
+ impl serde::Serialize for $key_type {
|
|
6
|
+ fn serialize<S>(
|
|
7
|
+ &self,
|
|
8
|
+ serializer: S,
|
|
9
|
+ ) -> std::result::Result<
|
|
10
|
+ <S as serde::Serializer>::Ok,
|
|
11
|
+ <S as serde::Serializer>::Error,
|
|
12
|
+ >
|
|
13
|
+ where
|
|
14
|
+ S: serde::Serializer,
|
|
15
|
+ {
|
|
16
|
+ serializer.serialize_str(&Key::string(self))
|
|
17
|
+ }
|
|
18
|
+ }
|
|
19
|
+
|
|
20
|
+ impl<'de> serde::Deserialize<'de> for $key_type {
|
|
21
|
+ fn deserialize<D>(
|
|
22
|
+ deserializer: D,
|
|
23
|
+ ) -> std::result::Result<Self, <D as serde::Deserializer<'de>>::Error>
|
|
24
|
+ where
|
|
25
|
+ D: serde::Deserializer<'de>,
|
|
26
|
+ {
|
|
27
|
+ let s = <String as serde::Deserialize>::deserialize(deserializer)?;
|
|
28
|
+ <$key_type>::from_string(&s).map_err(|err| {
|
|
29
|
+ serde::de::Error::custom(format!("Deserialization failed: `{}`", err))
|
|
30
|
+ })
|
|
31
|
+ }
|
|
32
|
+ }
|
|
33
|
+ };
|
|
34
|
+ }
|
|
35
|
+}
|
|
36
|
+
|
1
|
37
|
pub mod ed25519;
|
|
38
|
+pub mod key_exchange;
|
|
39
|
+pub mod prelude {
|
|
40
|
+ pub use super::{
|
|
41
|
+ ed25519::{ED25519PublicKey, ED25519SecretKey, ED25519Signature, Keypair},
|
|
42
|
+ key_exchange::{Public, Secret},
|
|
43
|
+ Error, Key,
|
|
44
|
+ };
|
|
45
|
+}
|
|
46
|
+
|
|
47
|
+use itertools::Itertools;
|
|
48
|
+
|
|
49
|
+type Result<T> = std::result::Result<T, Error>;
|
|
50
|
+
|
|
51
|
+pub(crate) const ED25519: &str = "ed25519";
|
|
52
|
+pub(crate) const X25519: &str = "x25519";
|
|
53
|
+
|
|
54
|
+/// ## Key
|
|
55
|
+/// **KEY_LENGTH** - It's a key size for ed25519 or x25519
|
|
56
|
+/// **KEY_TYPE** - Key type, for internal usage to reduce a boilerplate code.
|
|
57
|
+/// It's a prefix for a key string serialization. Possible values are ["ed25519", "x25519"]
|
|
58
|
+pub trait Key<const KEY_LENGTH: usize>: Sized {
|
|
59
|
+ const KEY_TYPE: &'static str;
|
|
60
|
+
|
|
61
|
+ fn from_string(key: &str) -> Result<Self> {
|
|
62
|
+ let (key_type, bs58_encoded) = split_encoded_str(key)?;
|
|
63
|
+
|
|
64
|
+ if key_type != Self::KEY_TYPE {
|
|
65
|
+ return Err(Error::WrongKeyType {
|
|
66
|
+ key_type: key_type.to_owned(),
|
|
67
|
+ expected_key_type: Self::KEY_TYPE,
|
|
68
|
+ });
|
|
69
|
+ }
|
|
70
|
+
|
|
71
|
+ let bytes = bs58::decode(bs58_encoded)
|
|
72
|
+ .into_vec()
|
|
73
|
+ .map_err(|err| Error::from_string::<Self>(bs58_encoded.to_owned(), err.to_string()))?;
|
|
74
|
+ Self::try_from_bytes(&bytes)
|
|
75
|
+ }
|
|
76
|
+
|
|
77
|
+ fn string(&self) -> String {
|
|
78
|
+ format!(
|
|
79
|
+ "{}:{}",
|
|
80
|
+ Self::KEY_TYPE,
|
|
81
|
+ bs58::encode(self.to_bytes()).into_string()
|
|
82
|
+ )
|
|
83
|
+ }
|
2
|
84
|
|
3
|
|
-use ed25519::ED25519Signature;
|
|
85
|
+ fn try_from_bytes(buf: &[u8]) -> Result<Self>;
|
|
86
|
+ fn to_bytes(&self) -> [u8; KEY_LENGTH];
|
|
87
|
+}
|
4
|
88
|
|
5
|
89
|
#[derive(thiserror::Error, Debug)]
|
6
|
90
|
pub enum Error {
|
7
|
|
- #[error(
|
8
|
|
- "Couldn't convert key from bytes `{key_string}` into `{key_name}`, because of: {cause}"
|
9
|
|
- )]
|
|
91
|
+ #[error("Couldn't convert key from bytes \"{data}\" into \"{key_name}\", because of: {cause}")]
|
10
|
92
|
ConvertFromBytes {
|
11
|
93
|
key_name: &'static str,
|
12
|
|
- key_string: String,
|
|
94
|
+ data: String,
|
13
|
95
|
cause: String,
|
14
|
96
|
},
|
15
|
97
|
#[error(
|
16
|
|
- "Couldn't convert key from string `{key_string}` into `{key_name}`, because of: {cause}"
|
|
98
|
+ "Couldn't convert key from string \"{data}\" into \"{key_name}\", because of: {cause}"
|
17
|
99
|
)]
|
18
|
100
|
ConvertFromString {
|
19
|
101
|
key_name: &'static str,
|
20
|
|
- key_string: String,
|
|
102
|
+ data: String,
|
21
|
103
|
cause: String,
|
22
|
104
|
},
|
23
|
|
- #[error("The key format `{0}` seems different from ed25519 format")]
|
|
105
|
+ #[error("The key format \"{0}\" seems different from ed25519 or x25519 format")]
|
24
|
106
|
UnknownKeyType(String),
|
25
|
|
- #[error("Signature `{0}` verification failed")]
|
26
|
|
- Verification(ED25519Signature),
|
|
107
|
+ #[error(
|
|
108
|
+ "The expected key type \"{expected_key_type}\" is different from actual \"{key_type}\""
|
|
109
|
+ )]
|
|
110
|
+ WrongKeyType {
|
|
111
|
+ key_type: String,
|
|
112
|
+ expected_key_type: &'static str,
|
|
113
|
+ },
|
|
114
|
+ #[error("Signature \"{0}\" verification failed")]
|
|
115
|
+ Verification(String),
|
27
|
116
|
}
|
28
|
117
|
|
29
|
118
|
impl Error {
|
30
|
|
- pub(crate) fn from_string<T>(key_string: String, cause: String) -> Self {
|
|
119
|
+ pub(crate) fn from_string<T>(data: String, cause: String) -> Self {
|
31
|
120
|
Self::ConvertFromString {
|
32
|
121
|
key_name: std::any::type_name::<T>()
|
33
|
122
|
.rsplit("::")
|
34
|
123
|
.next()
|
35
|
124
|
.unwrap_or_default(),
|
36
|
|
- key_string,
|
|
125
|
+ data,
|
37
|
126
|
cause,
|
38
|
127
|
}
|
39
|
128
|
}
|
|
@@ -44,8 +133,18 @@ impl Error {
|
44
|
133
|
.rsplit("::")
|
45
|
134
|
.next()
|
46
|
135
|
.unwrap_or_default(),
|
47
|
|
- key_string: bs58::encode(data).into_string(),
|
|
136
|
+ data: bs58::encode(data).into_string(),
|
48
|
137
|
cause,
|
49
|
138
|
}
|
50
|
139
|
}
|
51
|
140
|
}
|
|
141
|
+
|
|
142
|
+/// Split encoded [`str`] to key prefix and bs58 encoded string
|
|
143
|
+fn split_encoded_str(encoded: &str) -> Result<(&str, &str)> {
|
|
144
|
+ match encoded.split(':').next_tuple() {
|
|
145
|
+ Some((key_type @ ED25519, bs58_encoded) | (key_type @ X25519, bs58_encoded)) => {
|
|
146
|
+ Ok((key_type, bs58_encoded))
|
|
147
|
+ }
|
|
148
|
+ _ => Err(Error::UnknownKeyType(encoded.to_owned())),
|
|
149
|
+ }
|
|
150
|
+}
|