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}