Skip to main content

cliquenet/
x25519.rs

1use std::{cmp::Ordering, fmt};
2
3use ed25519_compact::x25519;
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
6#[cfg(feature = "serde")]
7use serde_bytes::ByteArray;
8
9#[derive(Clone, PartialEq, Eq, Hash)]
10pub struct Keypair {
11    pair: x25519::KeyPair,
12}
13
14#[derive(Copy, Clone, PartialEq, Eq, Hash)]
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
16pub struct PublicKey {
17    #[cfg_attr(
18        feature = "serde",
19        serde(
20            serialize_with = "serialize",
21            deserialize_with = "deserialize_x25519_pk"
22        )
23    )]
24    key: x25519::PublicKey,
25}
26
27#[derive(Clone, PartialEq, Eq, Hash)]
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
29pub struct SecretKey {
30    #[cfg_attr(
31        feature = "serde",
32        serde(
33            serialize_with = "serialize",
34            deserialize_with = "deserialize_x25519_sk"
35        )
36    )]
37    key: x25519::SecretKey,
38}
39
40impl Keypair {
41    pub fn generate() -> Result<Self, InvalidKeypair> {
42        let pair = x25519::KeyPair::generate();
43        if pair.validate().is_err() {
44            return Err(InvalidKeypair(()));
45        }
46        Ok(Self { pair })
47    }
48
49    pub fn from_seed(seed: [u8; 32]) -> Result<Self, InvalidKeypair> {
50        let sk = x25519::SecretKey::new(seed);
51        let Ok(pk) = sk.recover_public_key() else {
52            return Err(InvalidKeypair(()));
53        };
54        Ok(Self {
55            pair: x25519::KeyPair { sk, pk },
56        })
57    }
58
59    pub fn public_key(&self) -> PublicKey {
60        PublicKey { key: self.pair.pk }
61    }
62
63    pub fn secret_key(&self) -> SecretKey {
64        SecretKey {
65            key: self.pair.sk.clone(),
66        }
67    }
68}
69
70impl PublicKey {
71    pub fn as_bytes(&self) -> [u8; 32] {
72        *self.key
73    }
74
75    pub fn as_slice(&self) -> &[u8] {
76        &self.key[..]
77    }
78}
79
80impl SecretKey {
81    pub fn public_key(&self) -> PublicKey {
82        let key = self.key.recover_public_key().expect("valid public key");
83        PublicKey { key }
84    }
85
86    pub fn as_bytes(&self) -> [u8; 32] {
87        *self.key
88    }
89
90    pub fn as_slice(&self) -> &[u8] {
91        &self.key[..]
92    }
93}
94
95impl From<SecretKey> for Keypair {
96    fn from(k: SecretKey) -> Self {
97        let p = k.public_key();
98        Self {
99            pair: x25519::KeyPair {
100                sk: k.key,
101                pk: p.key,
102            },
103        }
104    }
105}
106
107impl From<&SecretKey> for Keypair {
108    fn from(k: &SecretKey) -> Self {
109        Self::from(k.clone())
110    }
111}
112
113impl From<SecretKey> for PublicKey {
114    fn from(k: SecretKey) -> Self {
115        k.public_key()
116    }
117}
118
119impl Ord for PublicKey {
120    fn cmp(&self, other: &Self) -> Ordering {
121        self.key[..].cmp(&other.key[..])
122    }
123}
124
125impl PartialOrd for PublicKey {
126    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
127        Some(self.cmp(other))
128    }
129}
130
131impl fmt::Debug for SecretKey {
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        f.write_str("SecretKey")
134    }
135}
136
137impl fmt::Debug for Keypair {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        f.debug_struct("Keypair")
140            .field("public_key", &self.public_key())
141            .field("secret_key", &"SecretKey")
142            .finish()
143    }
144}
145
146impl fmt::Debug for PublicKey {
147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148        write!(f, "{}", bs58::encode(&self.as_bytes()).into_string())
149    }
150}
151
152impl fmt::Display for PublicKey {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        <Self as fmt::Debug>::fmt(self, f)
155    }
156}
157
158impl TryFrom<&[u8]> for PublicKey {
159    type Error = InvalidPublicKey;
160
161    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
162        let key = x25519::PublicKey::from_slice(value).map_err(|_| InvalidPublicKey(()))?;
163        Ok(Self { key })
164    }
165}
166
167impl TryFrom<&[u8]> for SecretKey {
168    type Error = InvalidSecretKey;
169
170    fn try_from(s: &[u8]) -> Result<Self, Self::Error> {
171        let k = x25519::SecretKey::from_slice(s).map_err(|_| InvalidSecretKey(()))?;
172        if k.recover_public_key().is_err() {
173            return Err(InvalidSecretKey(()));
174        }
175        Ok(Self { key: k })
176    }
177}
178
179impl TryFrom<&str> for PublicKey {
180    type Error = InvalidPublicKey;
181
182    fn try_from(s: &str) -> Result<Self, Self::Error> {
183        bs58::decode(s)
184            .into_vec()
185            .map_err(|_| InvalidPublicKey(()))
186            .and_then(|v| PublicKey::try_from(v.as_slice()))
187    }
188}
189
190impl TryFrom<&str> for SecretKey {
191    type Error = InvalidSecretKey;
192
193    fn try_from(s: &str) -> Result<Self, Self::Error> {
194        bs58::decode(s)
195            .into_vec()
196            .map_err(|_| InvalidSecretKey(()))
197            .and_then(|v| SecretKey::try_from(v.as_slice()))
198    }
199}
200
201impl TryFrom<[u8; 32]> for SecretKey {
202    type Error = InvalidSecretKey;
203
204    fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
205        let key = x25519::SecretKey::new(bytes);
206        if key.recover_public_key().is_err() {
207            return Err(InvalidSecretKey(()));
208        }
209        Ok(SecretKey { key })
210    }
211}
212
213#[derive(Debug, thiserror::Error)]
214#[error("invalid keypair")]
215pub struct InvalidKeypair(());
216
217#[derive(Debug, thiserror::Error)]
218#[error("invalid secret key")]
219pub struct InvalidSecretKey(());
220
221#[derive(Debug, thiserror::Error)]
222#[error("invalid public key")]
223pub struct InvalidPublicKey(());
224
225#[cfg(feature = "serde")]
226fn serialize<S, T, const N: usize>(d: &T, s: S) -> Result<S::Ok, S::Error>
227where
228    S: Serializer,
229    T: std::ops::Deref<Target = [u8; N]>,
230{
231    if s.is_human_readable() {
232        bs58::encode(**d).into_string().serialize(s)
233    } else {
234        ByteArray::new(**d).serialize(s)
235    }
236}
237
238#[cfg(feature = "serde")]
239fn deserialize_x25519_pk<'de, D>(d: D) -> Result<x25519::PublicKey, D::Error>
240where
241    D: Deserializer<'de>,
242{
243    if d.is_human_readable() {
244        let s = String::deserialize(d)?;
245        let mut a = [0; 32];
246        let n = bs58::decode(&s).onto(&mut a).map_err(de::Error::custom)?;
247        x25519::PublicKey::from_slice(&a[..n]).map_err(de::Error::custom)
248    } else {
249        let a = ByteArray::<32>::deserialize(d)?;
250        x25519::PublicKey::from_slice(&a[..]).map_err(de::Error::custom)
251    }
252}
253
254#[cfg(feature = "serde")]
255fn deserialize_x25519_sk<'de, D>(d: D) -> Result<x25519::SecretKey, D::Error>
256where
257    D: Deserializer<'de>,
258{
259    if d.is_human_readable() {
260        let s = String::deserialize(d)?;
261        let mut a = [0; 32];
262        let n = bs58::decode(&s).onto(&mut a).map_err(de::Error::custom)?;
263        x25519::SecretKey::from_slice(&a[..n]).map_err(de::Error::custom)
264    } else {
265        let a = ByteArray::<32>::deserialize(d)?;
266        x25519::SecretKey::from_slice(&a[..]).map_err(de::Error::custom)
267    }
268}