1#[cfg(feature = "ed25519")]
2use std::convert::TryFrom;
3use std::str::FromStr;
4
5#[cfg(feature = "ed25519")]
6use curve25519_dalek::{edwards::CompressedEdwardsY, scalar::clamp_integer};
7#[cfg(feature = "ed25519")]
8use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey};
9#[cfg(feature = "ed25519")]
10use rand::{thread_rng, RngCore};
11#[cfg(feature = "ed25519")]
12use sha2::digest::Digest;
13use zeroize::Zeroize;
14
15use crate::utils::base58;
16use crate::{ConversionError, Validatable, ValidationError};
17
18mod types;
19pub use types::{KeyEncoding, KeyType};
20
21pub fn build_full_verkey(dest: &str, key: &str) -> Result<EncodedVerKey, ConversionError> {
23 EncodedVerKey::from_str_qualified(key, Some(dest), None, None)
24}
25
26#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
28pub struct PrivateKey {
29 pub key: Box<[u8]>,
30 pub alg: KeyType,
31}
32
33impl PrivateKey {
34 pub fn new<K: AsRef<[u8]>>(key: K, alg: Option<KeyType>) -> Self {
35 Self {
36 key: key.as_ref().into(),
37 alg: alg.unwrap_or_default(),
38 }
39 }
40
41 #[cfg(feature = "ed25519")]
42 pub fn generate(alg: Option<KeyType>) -> Result<Self, ConversionError> {
43 let alg = alg.unwrap_or_default();
44 match alg {
45 KeyType::ED25519 => {
46 let mut sk = [0u8; 32];
47 thread_rng().fill_bytes(&mut sk[..]);
48 Self::from_seed(&sk[..])
49 }
50 _ => Err("Unsupported key type".into()),
51 }
52 }
53
54 #[cfg(feature = "ed25519")]
55 pub fn from_seed(seed: &[u8]) -> Result<Self, ConversionError> {
56 let sk = SigningKey::from_bytes(
57 seed.try_into()
58 .map_err(|_| "Invalid length for secret key")?,
59 );
60 Ok(Self::new(sk.to_keypair_bytes(), Some(KeyType::ED25519)))
61 }
62
63 pub fn public_key(&self) -> Result<VerKey, ConversionError> {
64 match self.alg {
65 KeyType::ED25519 => Ok(VerKey::new(&self.key[32..], Some(self.alg.clone()))),
66 _ => Err("Unsupported key type".into()),
67 }
68 }
69
70 pub fn key_bytes(&self) -> Vec<u8> {
71 Vec::from(self.key.as_ref())
72 }
73
74 #[cfg(feature = "ed25519")]
75 pub fn key_exchange(&self) -> Result<Self, ConversionError> {
76 match self.alg {
77 KeyType::ED25519 => {
78 let mut hash = sha2::Sha512::digest(&self.key[..32]);
79 let x_sk =
80 x25519_dalek::StaticSecret::from(clamp_integer(hash[..32].try_into().unwrap()));
81 hash.zeroize();
82 Ok(Self::new(x_sk.to_bytes(), Some(KeyType::X25519)))
83 }
84 _ => Err("Unsupported key format for key exchange".into()),
85 }
86 }
87
88 #[cfg(feature = "ed25519")]
89 pub fn sign<M: AsRef<[u8]>>(&self, message: M) -> Result<Vec<u8>, ConversionError> {
90 match self.alg {
91 KeyType::ED25519 => {
92 let esk = SigningKey::from_keypair_bytes((&*self.key).try_into().unwrap()).unwrap();
93 let sig = esk.sign(message.as_ref());
94 Ok(sig.to_bytes().into())
95 }
96 _ => Err("Unsupported key format for signing".into()),
97 }
98 }
99}
100
101impl AsRef<[u8]> for PrivateKey {
102 fn as_ref(&self) -> &[u8] {
103 self.key.as_ref()
104 }
105}
106
107impl Zeroize for PrivateKey {
108 fn zeroize(&mut self) {
109 self.key.zeroize();
110 self.alg = KeyType::from("")
111 }
112}
113
114impl Drop for PrivateKey {
115 fn drop(&mut self) {
116 self.zeroize()
117 }
118}
119
120impl Validatable for PrivateKey {
121 fn validate(&self) -> Result<(), ValidationError> {
122 if self.alg == KeyType::ED25519 {
123 if self.key.len() == 64 {
124 Ok(())
125 } else {
126 Err("Invalid signing key length".into())
127 }
128 } else {
129 Err("Unsupported signing key type".into())
130 }
131 }
132}
133
134#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
136pub struct VerKey {
137 pub key: Box<[u8]>,
138 pub alg: KeyType,
139}
140
141impl VerKey {
142 pub fn new<K: AsRef<[u8]>>(key: K, alg: Option<KeyType>) -> Self {
143 let alg = alg.unwrap_or_default();
144 Self {
145 key: key.as_ref().into(),
146 alg,
147 }
148 }
149
150 pub fn as_base58(&self) -> Result<EncodedVerKey, ConversionError> {
151 self.encode(&KeyEncoding::BASE58)
152 }
153
154 pub fn encode(&self, enc: &KeyEncoding) -> Result<EncodedVerKey, ConversionError> {
155 match enc {
156 KeyEncoding::BASE58 => {
157 let key = base58::encode(&self.key);
158 Ok(EncodedVerKey::new(
159 key.as_str(),
160 Some(self.alg.clone()),
161 Some(enc.clone()),
162 ))
163 }
164 _ => Err("Unsupported key encoding".into()),
165 }
166 }
167
168 pub fn key_bytes(&self) -> Vec<u8> {
169 Vec::from(self.key.as_ref())
170 }
171
172 #[cfg(feature = "ed25519")]
173 pub fn key_exchange(&self) -> Result<Self, ConversionError> {
174 match self.alg {
175 KeyType::ED25519 => {
176 let vky = CompressedEdwardsY::from_slice(&self.key).unwrap();
177 if let Some(x_vk) = vky.decompress() {
178 Ok(Self::new(
179 x_vk.to_montgomery().as_bytes(),
180 Some(KeyType::X25519),
181 ))
182 } else {
183 Err("Error converting to x25519 key".into())
184 }
185 }
186 _ => Err("Unsupported verkey type".into()),
187 }
188 }
189
190 #[cfg(feature = "ed25519")]
191 pub fn verify_signature<M: AsRef<[u8]>, S: AsRef<[u8]>>(
192 &self,
193 message: M,
194 signature: S,
195 ) -> Result<bool, ConversionError> {
196 match self.alg {
197 KeyType::ED25519 => {
198 let vk = VerifyingKey::try_from(&*self.key).unwrap();
199 if let Ok(sig) = Signature::try_from(signature.as_ref()) {
200 Ok(vk.verify_strict(message.as_ref(), &sig).is_ok())
201 } else {
202 Err("Error validating message signature".into())
203 }
204 }
205 _ => Err("Unsupported verkey type".into()),
206 }
207 }
208}
209
210impl AsRef<[u8]> for VerKey {
211 fn as_ref(&self) -> &[u8] {
212 self.key.as_ref()
213 }
214}
215
216impl std::fmt::Display for VerKey {
217 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
218 match &self.as_base58() {
219 Ok(k) => k.fmt(f),
220 Err(err) => write!(f, "<Error encoding key: {}>", err),
221 }
222 }
223}
224
225impl Validatable for VerKey {
226 fn validate(&self) -> Result<(), ValidationError> {
227 if self.alg == KeyType::ED25519 {
228 let bytes = self.key_bytes();
229 if bytes.len() == 32 {
230 Ok(())
231 } else {
232 Err("Invalid verkey length".into())
233 }
234 } else {
235 Err("Unsupported verkey type".into())
236 }
237 }
238}
239
240impl Zeroize for VerKey {
241 fn zeroize(&mut self) {
242 self.key.zeroize();
243 self.alg = KeyType::from("");
244 }
245}
246
247impl Drop for VerKey {
248 fn drop(&mut self) {
249 self.zeroize()
250 }
251}
252
253#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
255pub struct EncodedVerKey {
256 pub key: String,
257 pub alg: KeyType,
258 pub enc: KeyEncoding,
259}
260
261impl EncodedVerKey {
262 pub fn new<K: AsRef<str>>(key: K, alg: Option<KeyType>, enc: Option<KeyEncoding>) -> Self {
263 let alg = alg.unwrap_or_default();
264 let enc = enc.unwrap_or_default();
265 Self {
266 key: key.as_ref().to_owned(),
267 alg,
268 enc,
269 }
270 }
271
272 pub fn from_did_and_verkey(did: &str, key: &str) -> Result<Self, ConversionError> {
273 if let Some(key) = key.strip_prefix('~') {
274 let mut vk_bytes = base58::decode(key)?;
275 if vk_bytes.len() != 16 {
276 return Err("Expected 16-byte abbreviated verkey".into());
277 }
278 let mut did_bytes = base58::decode(did)?;
279 if did_bytes.len() != 16 {
280 return Err("DID must be 16 bytes in length".into());
281 }
282 did_bytes.append(&mut vk_bytes);
283 Ok(Self::new(
284 base58::encode(did_bytes),
285 Some(KeyType::ED25519),
286 Some(KeyEncoding::BASE58),
287 ))
288 } else {
289 Ok(Self::new(
290 key,
291 Some(KeyType::ED25519),
292 Some(KeyEncoding::BASE58),
293 ))
294 }
295 }
296
297 pub fn abbreviated_for_did(&self, did: &str) -> Result<String, ConversionError> {
298 let did_bytes = base58::decode(did)?;
299 if did_bytes.len() != 16 {
300 return Err("DID must be 16 bytes in length".into());
301 }
302 let vk = self.key_bytes()?;
303 if vk.len() != 32 {
304 return Err("Expected 32-byte verkey".into());
305 }
306 if &vk[..16] == did_bytes.as_slice() {
307 let mut result = "~".to_string();
308 result.push_str(&base58::encode(&vk[16..]));
309 Ok(result)
310 } else {
311 Ok(base58::encode(vk))
312 }
313 }
314
315 pub fn decode(&self) -> Result<VerKey, ConversionError> {
316 let mut vk = self.key_bytes()?;
317 let result = VerKey::new(&vk, Some(self.alg.clone()));
318 vk.zeroize();
319 Ok(result)
320 }
321
322 pub fn from_slice<K: AsRef<[u8]>>(key: K) -> Result<Self, ConversionError> {
323 let key = std::str::from_utf8(key.as_ref())?;
324 Self::from_str_qualified(key, None, None, None)
325 }
326
327 pub fn from_str_qualified(
328 key: &str,
329 dest: Option<&str>,
330 alg: Option<KeyType>,
331 enc: Option<KeyEncoding>,
332 ) -> Result<Self, ConversionError> {
333 let (key, alg) = if key.contains(':') {
334 let splits: Vec<&str> = key.splitn(2, ':').collect();
335 let alg = match splits[1] {
336 "" => alg,
337 _ => Some(splits[1].into()),
338 };
339 (splits[0], alg)
340 } else {
341 (key, alg)
342 };
343
344 if let Some(key) = key.strip_prefix('~') {
345 let dest = dest.ok_or("Destination required for short verkey")?;
346 let mut result = base58::decode(dest)?;
347 let mut end = base58::decode(key)?;
348 result.append(&mut end);
349 Ok(Self::new(base58::encode(result), alg, enc))
350 } else {
351 Ok(Self::new(key, alg, enc))
352 }
353 }
354
355 pub fn long_form(&self) -> String {
356 let mut result = self.key.clone();
357 result.push(':');
358 result.push_str(&self.alg);
359 result
360 }
361
362 pub fn as_base58(self) -> Result<Self, ConversionError> {
363 match self.enc {
364 KeyEncoding::BASE58 => Ok(self),
365 _ => {
366 let key = base58::encode(self.key_bytes()?);
367 Ok(Self::new(
368 key.as_str(),
369 Some(self.alg.clone()),
370 Some(KeyEncoding::BASE58),
371 ))
372 }
373 }
374 }
375
376 pub fn key_bytes(&self) -> Result<Vec<u8>, ConversionError> {
377 match self.enc {
378 KeyEncoding::BASE58 => Ok(base58::decode(&self.key)?),
379 _ => Err("Unsupported verkey encoding".into()),
380 }
381 }
382
383 pub fn encoded_key_bytes(&self) -> &[u8] {
384 self.key.as_bytes()
385 }
386
387 #[cfg(feature = "ed25519")]
388 pub fn key_exchange(&self) -> Result<VerKey, ConversionError> {
389 let vk = self.decode()?;
390 vk.key_exchange()
391 }
392
393 #[cfg(feature = "ed25519")]
394 pub fn key_exchange_encoded(&self) -> Result<Self, ConversionError> {
395 let x_vk = self.key_exchange()?;
396 x_vk.encode(&self.enc)
397 }
398
399 #[cfg(feature = "ed25519")]
400 pub fn verify_signature<M: AsRef<[u8]>, S: AsRef<[u8]>>(
401 &self,
402 message: M,
403 signature: S,
404 ) -> Result<bool, ConversionError> {
405 let vk = self.decode()?;
406 vk.verify_signature(message, signature)
407 }
408}
409
410impl std::fmt::Display for EncodedVerKey {
411 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
412 let out = if self.alg == KeyType::default() {
413 self.key.clone()
414 } else {
415 self.long_form()
416 };
417 f.write_str(out.as_str())
418 }
419}
420
421impl FromStr for EncodedVerKey {
422 type Err = ConversionError;
423
424 fn from_str(key: &str) -> Result<Self, ConversionError> {
425 Self::from_str_qualified(key, None, None, None)
426 }
427}
428
429impl Validatable for EncodedVerKey {
430 fn validate(&self) -> Result<(), ValidationError> {
431 let verkey = self.decode()?;
432 verkey.validate()
433 }
434}
435
436impl Zeroize for EncodedVerKey {
437 fn zeroize(&mut self) {
438 self.key.zeroize();
439 self.alg = KeyType::from("");
440 self.enc = KeyEncoding::from("")
441 }
442}
443
444impl Drop for EncodedVerKey {
445 fn drop(&mut self) {
446 self.zeroize()
447 }
448}
449
450#[cfg(test)]
451mod tests {
452 use super::*;
453
454 #[test]
455 fn from_str_empty() {
456 assert_eq!(
457 EncodedVerKey::from_str("").unwrap(),
458 EncodedVerKey::new("", Some(KeyType::default()), Some(KeyEncoding::default()))
459 )
460 }
461
462 #[test]
463 fn from_str_single_colon() {
464 assert_eq!(
465 EncodedVerKey::from_str(":").unwrap(),
466 EncodedVerKey::new("", Some(KeyType::default()), Some(KeyEncoding::default()))
467 )
468 }
469
470 #[test]
471 fn from_str_ends_with_colon() {
472 assert_eq!(
473 EncodedVerKey::from_str("foo:").unwrap(),
474 EncodedVerKey::new(
475 "foo",
476 Some(KeyType::default()),
477 Some(KeyEncoding::default())
478 )
479 )
480 }
481
482 #[test]
483 fn from_key_starts_with_colon() {
484 assert_eq!(
485 EncodedVerKey::from_str(":bar").unwrap(),
486 EncodedVerKey::new("", Some("bar".into()), Some(KeyEncoding::default()))
487 )
488 }
489
490 #[test]
491 fn from_key_works() {
492 assert_eq!(
493 EncodedVerKey::from_str("foo:bar:baz").unwrap(),
494 EncodedVerKey::new("foo", Some("bar:baz".into()), Some(KeyEncoding::default()))
495 )
496 }
497
498 #[test]
499 fn round_trip_verkey() {
500 assert_eq!(
501 EncodedVerKey::from_str("foo:bar:baz").unwrap().long_form(),
502 "foo:bar:baz"
503 )
504 }
505
506 #[cfg(feature = "ed25519")]
507 #[test]
508 fn key_from_seed() {
509 const SEED: &[u8; 32] = b"aaaabbbbccccddddeeeeffffgggghhhh";
510 let sk = PrivateKey::from_seed(&SEED[..]).unwrap();
511 assert_eq!(
512 sk.as_ref(),
513 &[
514 97, 97, 97, 97, 98, 98, 98, 98, 99, 99, 99, 99, 100, 100, 100, 100, 101, 101, 101,
515 101, 102, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 104, 113, 22, 13, 44,
516 71, 184, 166, 148, 196, 234, 85, 148, 234, 22, 204, 148, 187, 247, 77, 119, 250,
517 28, 37, 255, 29, 31, 159, 159, 245, 68, 107, 235
518 ]
519 );
520 let xk = sk.key_exchange().unwrap();
521 assert_eq!(
522 xk.as_ref(),
523 &[
524 208, 235, 232, 147, 241, 214, 250, 182, 45, 157, 20, 202, 31, 184, 226, 115, 149,
525 82, 210, 89, 50, 100, 22, 67, 21, 8, 124, 198, 100, 252, 237, 107
526 ]
527 );
528 }
529
530 #[cfg(feature = "ed25519")]
531 #[test]
532 fn sign_and_verify() {
533 let message = b"hello there";
534 let sk = PrivateKey::generate(None).unwrap();
535 let sig = sk.sign(message).unwrap();
536 let vk = sk.public_key().unwrap();
537 assert!(vk.verify_signature(message, &sig).unwrap());
538 assert!(vk.verify_signature(message, b"").is_err());
539 assert!(!vk.verify_signature("goodbye", &sig).unwrap());
540 }
541
542 #[cfg(feature = "ed25519")]
543 #[test]
544 fn validate_keys() {
545 let sk = PrivateKey::generate(None).unwrap();
546 sk.validate().unwrap();
547 let vk = sk.public_key().unwrap();
548 vk.validate().unwrap();
549
550 let sk = PrivateKey::new(b"bad key", Some(KeyType::ED25519));
551 assert!(sk.validate().is_err());
552 let vk = VerKey::new(b"bad key", Some(KeyType::ED25519));
553 assert!(vk.validate().is_err());
554 }
555}