浏览代码

Add diffie-hellman keys exchange

develop
Silvestr Predko 2 年前
父节点
当前提交
132fb53e03
共有 5 个文件被更改,包括 245 次插入22 次删除
  1. 3
    5
      common-api/Cargo.toml
  2. 1
    1
      common-api/src/crypto/ed25519.rs
  3. 129
    0
      common-api/src/crypto/key_exchange.rs
  4. 112
    13
      common-api/src/crypto/mod.rs
  5. 0
    3
      common-api/src/lib.rs

+ 3
- 5
common-api/Cargo.toml 查看文件

@@ -4,14 +4,11 @@ version = "0.1.0"
4 4
 edition = "2021"
5 5
 authors = ["silvestr@relayz.io"]
6 6
 description = """
7
-This crate is used between many other crates to provide the same
7
+This crate is used between other crates to provide the same
8 8
 API for signing data and shared types. Please note that all data
9 9
 structures should be serializable with "serde" and "borsh"
10 10
 """
11 11
 
12
-[lib]
13
-crate-type = ["cdylib", "rlib"]
14
-
15 12
 [dependencies]
16 13
 base64 = "0.13"
17 14
 bs58 = "0.4"
@@ -19,5 +16,6 @@ borsh = "0.9"
19 16
 ed25519-dalek = "1"
20 17
 itertools = "0.10"
21 18
 serde = { version = "1", default-features = false, features = ["derive"] }
22
-serde_json = { version = "1", default-features = false }
19
+serde_json = "1"
23 20
 thiserror = "1"
21
+x25519-dalek = { version = "1", features = ["serde"] }

+ 1
- 1
common-api/src/crypto/ed25519.rs 查看文件

@@ -44,7 +44,7 @@ impl ED25519PublicKey {
44 44
     pub fn verify(&self, data: &[u8], signature: &ED25519Signature) -> Result<()> {
45 45
         self.0
46 46
             .verify(data, &signature.0)
47
-            .map_err(|_| Error::Verification(*signature))
47
+            .map_err(|_| Error::Verification(bs58::encode(data).into_string()))
48 48
     }
49 49
 
50 50
     #[inline]

+ 129
- 0
common-api/src/crypto/key_exchange.rs 查看文件

@@ -0,0 +1,129 @@
1
+//! ### Diffie–Hellman key exchange with ed25519 elliptic curves algorithm
2
+//! ---
3
+//! Used Dalek cryptography, and implemented [`Borsh`](https://borsh.io/) serialization for it
4
+
5
+use borsh::{BorshDeserialize, BorshSerialize};
6
+use std::{
7
+    fmt::Display,
8
+    io::{Error as IoError, ErrorKind},
9
+};
10
+use x25519_dalek::{PublicKey, StaticSecret};
11
+
12
+use super::{Error, Key, Result, X25519};
13
+
14
+const PUBLIC_LENGTH: usize = 32_usize;
15
+const SECRET_LENGTH: usize = 32_usize;
16
+
17
+pub struct Secret(StaticSecret);
18
+
19
+impl BorshSerialize for Secret {
20
+    fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
21
+        writer.write_all(&self.0.to_bytes())
22
+    }
23
+}
24
+
25
+impl BorshDeserialize for Secret {
26
+    fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
27
+        let secret_key = Secret::try_from_bytes(std::mem::take(buf))
28
+            .map_err(|err| IoError::new(ErrorKind::InvalidData, err.to_string()))?;
29
+        Ok(secret_key)
30
+    }
31
+}
32
+
33
+#[derive(Copy, Clone, PartialEq, Eq)]
34
+pub struct Public(PublicKey);
35
+
36
+impl BorshSerialize for Public {
37
+    fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
38
+        writer.write_all(self.0.as_bytes())
39
+    }
40
+}
41
+
42
+impl BorshDeserialize for Public {
43
+    fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
44
+        let public_key = Public::try_from_bytes(std::mem::take(buf))
45
+            .map_err(|err| IoError::new(ErrorKind::InvalidData, err.to_string()))?;
46
+        Ok(public_key)
47
+    }
48
+}
49
+
50
+impl Display for Public {
51
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52
+        write!(f, "{}", self.string())
53
+    }
54
+}
55
+
56
+impl Key<SECRET_LENGTH> for Secret {
57
+    const KEY_TYPE: &'static str = X25519;
58
+
59
+    #[inline]
60
+    fn to_bytes(&self) -> [u8; SECRET_LENGTH] {
61
+        self.0.to_bytes()
62
+    }
63
+
64
+    fn try_from_bytes(buf: &[u8]) -> Result<Self> {
65
+        if buf.len() != SECRET_LENGTH {
66
+            return Err(Error::from_bytes::<Public>(
67
+                buf,
68
+                format!(
69
+                    "input buffer size \"{}\" not equal to secret key size \"{SECRET_LENGTH}\"",
70
+                    buf.len()
71
+                ),
72
+            ));
73
+        }
74
+
75
+        let mut temp_buf = [0_u8; SECRET_LENGTH];
76
+        temp_buf.copy_from_slice(buf);
77
+
78
+        Ok(Self(StaticSecret::from(temp_buf)))
79
+    }
80
+}
81
+
82
+impl Key<PUBLIC_LENGTH> for Public {
83
+    const KEY_TYPE: &'static str = X25519;
84
+
85
+    #[inline]
86
+    fn to_bytes(&self) -> [u8; PUBLIC_LENGTH] {
87
+        self.0.to_bytes()
88
+    }
89
+
90
+    fn try_from_bytes(buf: &[u8]) -> Result<Self> {
91
+        if buf.len() != PUBLIC_LENGTH {
92
+            return Err(Error::from_bytes::<Public>(
93
+                buf,
94
+                format!(
95
+                    "input buffer size \"{}\" not equal to public key size \"{PUBLIC_LENGTH}\"",
96
+                    buf.len()
97
+                ),
98
+            ));
99
+        }
100
+
101
+        let mut temp_buf = [0_u8; PUBLIC_LENGTH];
102
+        temp_buf.copy_from_slice(buf);
103
+
104
+        Ok(Self(PublicKey::from(temp_buf)))
105
+    }
106
+}
107
+
108
+impl<'a> From<&'a Secret> for Public {
109
+    fn from(secret: &'a Secret) -> Public {
110
+        Self(PublicKey::from(&secret.0))
111
+    }
112
+}
113
+
114
+impl Secret {
115
+    /// Creates a secret part from other participant public part of keypair
116
+    ///
117
+    /// ## Arguments
118
+    /// - **other_public** - Another public part [`Public`] of the key exchange process
119
+    ///
120
+    /// ## Returns
121
+    /// Byte array with a shared secret key
122
+    ///
123
+    pub fn exchange(&self, other_public: &Public) -> [u8; SECRET_LENGTH] {
124
+        self.0.diffie_hellman(&other_public.0).to_bytes()
125
+    }
126
+}
127
+
128
+serde_impl!(Secret);
129
+serde_impl!(Public);

+ 112
- 13
common-api/src/crypto/mod.rs 查看文件

@@ -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
+}

+ 0
- 3
common-api/src/lib.rs 查看文件

@@ -1,4 +1 @@
1 1
 pub mod crypto;
2
-
3
-#[cfg(test)]
4
-mod tests {}

正在加载...
取消
保存