1#[cfg(feature = "ed25519")]
2use curve25519_dalek::edwards::CompressedEdwardsY;
3#[cfg(feature = "ed25519")]
4use ed25519_dalek::{ExpandedSecretKey, PublicKey, SecretKey, Signature};
5#[cfg(feature = "ed25519")]
6use rand::{thread_rng, RngCore};
7#[cfg(feature = "ed25519")]
8use sha2::digest::Digest;
9
10#[cfg(feature = "ed25519")]
11use std::convert::TryFrom;
12
13use zeroize::Zeroize;
14
15use super::base58;
16use super::error::ConversionError;
17use super::{Validatable, ValidationError};
18
19mod types;
20pub use types::{KeyEncoding, KeyType};
21
22pub fn build_full_verkey(dest: &str, key: &str) -> Result<EncodedVerKey, ConversionError> {
24 EncodedVerKey::from_str_qualified(key, Some(dest), None, None)
25}
26
27#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct PrivateKey {
30 pub key: Vec<u8>,
31 pub alg: KeyType,
32}
33
34impl PrivateKey {
35 pub fn new<K: AsRef<[u8]>>(key: K, alg: Option<KeyType>) -> Self {
36 Self {
37 key: key.as_ref().to_vec(),
38 alg: alg.unwrap_or_default(),
39 }
40 }
41
42 #[cfg(feature = "ed25519")]
43 pub fn generate(alg: Option<KeyType>) -> Result<Self, ConversionError> {
44 let alg = alg.unwrap_or_default();
45 match alg {
46 KeyType::ED25519 => {
47 let mut sk = [0u8; 32];
48 thread_rng().fill_bytes(&mut sk[..]);
49 Self::from_seed(&sk[..])
50 }
51 _ => Err("Unsupported key type".into()),
52 }
53 }
54
55 #[cfg(feature = "ed25519")]
56 pub fn from_seed(seed: &[u8]) -> Result<Self, ConversionError> {
57 let sk = SecretKey::from_bytes(seed)
58 .map_err(|err| format!("Error creating signing key: {}", err))?;
59 let mut esk = [0u8; 64];
60 esk[..32].copy_from_slice(sk.as_bytes());
61 esk[32..].copy_from_slice(PublicKey::from(&sk).as_bytes());
62 Ok(Self::new(esk, Some(KeyType::ED25519)))
63 }
64
65 pub fn public_key(&self) -> Result<VerKey, ConversionError> {
66 match self.alg {
67 KeyType::ED25519 => Ok(VerKey::new(&self.key[32..], Some(self.alg.clone()))),
68 _ => Err("Unsupported key type".into()),
69 }
70 }
71
72 pub fn key_bytes(&self) -> Vec<u8> {
73 self.key.clone()
74 }
75
76 #[cfg(feature = "ed25519")]
77 pub fn key_exchange(&self) -> Result<Self, ConversionError> {
78 match self.alg {
79 KeyType::ED25519 => {
80 let mut hash = sha2::Sha512::digest(&self.key[..32]);
81 let x_sk =
82 x25519_dalek::StaticSecret::from(<[u8; 32]>::try_from(&hash[..32]).unwrap());
83 hash.zeroize();
84 Ok(Self::new(&x_sk.to_bytes(), Some(KeyType::X25519)))
85 }
86 _ => Err("Unsupported key format for key exchange".into()),
87 }
88 }
89
90 #[cfg(feature = "ed25519")]
91 pub fn sign<M: AsRef<[u8]>>(&self, message: M) -> Result<Vec<u8>, ConversionError> {
92 match self.alg {
93 KeyType::ED25519 => {
94 let esk = ExpandedSecretKey::from(&SecretKey::from_bytes(&self.key[..32]).unwrap());
95 let pk = PublicKey::from_bytes(&self.key[32..]).unwrap();
96 let sig = esk.sign(message.as_ref(), &pk);
97 Ok(sig.to_bytes().into())
98 }
99 _ => Err("Unsupported key format for signing".into()),
100 }
101 }
102}
103
104impl AsRef<[u8]> for PrivateKey {
105 fn as_ref(&self) -> &[u8] {
106 self.key.as_ref()
107 }
108}
109
110impl Zeroize for PrivateKey {
111 fn zeroize(&mut self) {
112 self.key.zeroize();
113 self.alg = KeyType::from("")
114 }
115}
116
117impl Drop for PrivateKey {
118 fn drop(&mut self) {
119 self.zeroize()
120 }
121}
122
123impl Validatable for PrivateKey {
124 fn validate(&self) -> Result<(), ValidationError> {
125 if self.alg == KeyType::ED25519 {
126 if self.key.len() == 64 {
127 Ok(())
128 } else {
129 Err("Invalid signing key length".into())
130 }
131 } else {
132 Err("Unsupported signing key type".into())
133 }
134 }
135}
136
137#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
139pub struct VerKey {
140 pub key: Vec<u8>,
141 pub alg: KeyType,
142}
143
144impl VerKey {
145 pub fn new<K: AsRef<[u8]>>(key: K, alg: Option<KeyType>) -> Self {
146 let alg = alg.unwrap_or_default();
147 Self {
148 key: key.as_ref().to_vec(),
149 alg,
150 }
151 }
152
153 pub fn as_base58(&self) -> Result<EncodedVerKey, ConversionError> {
154 self.encode(&KeyEncoding::BASE58)
155 }
156
157 pub fn encode(&self, enc: &KeyEncoding) -> Result<EncodedVerKey, ConversionError> {
158 match enc {
159 KeyEncoding::BASE58 => {
160 let key = base58::encode(&self.key);
161 Ok(EncodedVerKey::new(
162 key.as_str(),
163 Some(self.alg.clone()),
164 Some(enc.clone()),
165 ))
166 }
167 _ => Err("Unsupported key encoding".into()),
168 }
169 }
170
171 pub fn key_bytes(&self) -> Vec<u8> {
172 self.key.clone()
173 }
174
175 #[cfg(feature = "ed25519")]
176 pub fn key_exchange(&self) -> Result<Self, ConversionError> {
177 match self.alg {
178 KeyType::ED25519 => {
179 let vky = CompressedEdwardsY::from_slice(&self.key[..]);
180 if let Some(x_vk) = vky.decompress() {
181 Ok(Self::new(
182 x_vk.to_montgomery().as_bytes().to_vec(),
183 Some(KeyType::X25519),
184 ))
185 } else {
186 Err("Error converting to x25519 key".into())
187 }
188 }
189 _ => Err("Unsupported verkey type".into()),
190 }
191 }
192
193 #[cfg(feature = "ed25519")]
194 pub fn verify_signature<M: AsRef<[u8]>, S: AsRef<[u8]>>(
195 &self,
196 message: M,
197 signature: S,
198 ) -> Result<bool, ConversionError> {
199 match self.alg {
200 KeyType::ED25519 => {
201 let vk = PublicKey::from_bytes(&self.key[..]).unwrap();
202 if let Ok(sig) = Signature::try_from(signature.as_ref()) {
203 Ok(vk.verify_strict(message.as_ref(), &sig).is_ok())
204 } else {
205 Err("Error validating message signature".into())
206 }
207 }
208 _ => Err("Unsupported verkey type".into()),
209 }
210 }
211}
212
213impl AsRef<[u8]> for VerKey {
214 fn as_ref(&self) -> &[u8] {
215 self.key.as_ref()
216 }
217}
218
219impl std::fmt::Display for VerKey {
220 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221 match &self.as_base58() {
222 Ok(k) => k.fmt(f),
223 Err(err) => write!(f, "<Error encoding key: {}>", err),
224 }
225 }
226}
227
228impl Validatable for VerKey {
229 fn validate(&self) -> Result<(), ValidationError> {
230 if self.alg == KeyType::ED25519 {
231 let bytes = self.key_bytes();
232 if bytes.len() == 32 {
233 Ok(())
234 } else {
235 Err("Invalid verkey length".into())
236 }
237 } else {
238 Err("Unsupported verkey type".into())
239 }
240 }
241}
242
243impl Zeroize for VerKey {
244 fn zeroize(&mut self) {
245 self.key.zeroize();
246 self.alg = KeyType::from("");
247 }
248}
249
250impl Drop for VerKey {
251 fn drop(&mut self) {
252 self.zeroize()
253 }
254}
255
256#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
258pub struct EncodedVerKey {
259 pub key: String,
260 pub alg: KeyType,
261 pub enc: KeyEncoding,
262}
263
264impl EncodedVerKey {
265 pub fn new<K: AsRef<str>>(key: K, alg: Option<KeyType>, enc: Option<KeyEncoding>) -> Self {
266 let alg = alg.unwrap_or_default();
267 let enc = enc.unwrap_or_default();
268 Self {
269 key: key.as_ref().to_owned(),
270 alg,
271 enc,
272 }
273 }
274
275 pub fn from_did_and_verkey(did: &str, key: &str) -> Result<Self, ConversionError> {
276 if key.chars().next() == Some('~') {
277 let mut vk_bytes = base58::decode(&key[1..])?;
278 if vk_bytes.len() != 16 {
279 return Err("Expected 16-byte abbreviated verkey".into());
280 }
281 let mut did_bytes = base58::decode(did)?;
282 if did_bytes.len() != 16 {
283 return Err("DID must be 16 bytes in length".into());
284 }
285 did_bytes.append(&mut vk_bytes);
286 Ok(Self::new(
287 &base58::encode(did_bytes),
288 Some(KeyType::ED25519),
289 Some(KeyEncoding::BASE58),
290 ))
291 } else {
292 Ok(Self::new(
293 key,
294 Some(KeyType::ED25519),
295 Some(KeyEncoding::BASE58),
296 ))
297 }
298 }
299
300 pub fn abbreviated_for_did(&self, did: &str) -> Result<String, ConversionError> {
301 let did_bytes = base58::decode(did)?;
302 if did_bytes.len() != 16 {
303 return Err("DID must be 16 bytes in length".into());
304 }
305 let vk = self.key_bytes()?;
306 if vk.len() != 32 {
307 return Err("Expected 32-byte verkey".into());
308 }
309 if &vk[..16] == did_bytes.as_slice() {
310 let mut result = "~".to_string();
311 result.push_str(&base58::encode(&vk[16..]));
312 Ok(result)
313 } else {
314 Ok(base58::encode(vk))
315 }
316 }
317
318 pub fn decode(&self) -> Result<VerKey, ConversionError> {
319 let mut vk = self.key_bytes()?;
320 let result = VerKey::new(&vk, Some(self.alg.clone()));
321 vk.zeroize();
322 Ok(result)
323 }
324
325 pub fn from_slice<K: AsRef<[u8]>>(key: K) -> Result<Self, ConversionError> {
326 let key = std::str::from_utf8(key.as_ref())?;
327 Self::from_str_qualified(key, None, None, None)
328 }
329
330 pub fn from_str(key: &str) -> Result<Self, ConversionError> {
331 Self::from_str_qualified(key, None, None, None)
332 }
333
334 pub fn from_str_qualified(
335 key: &str,
336 dest: Option<&str>,
337 alg: Option<KeyType>,
338 enc: Option<KeyEncoding>,
339 ) -> Result<Self, ConversionError> {
340 let (key, alg) = if key.contains(':') {
341 let splits: Vec<&str> = key.splitn(2, ':').collect();
342 let alg = match splits[1] {
343 "" => alg,
344 _ => Some(splits[1].into()),
345 };
346 (splits[0], alg)
347 } else {
348 (key, alg)
349 };
350
351 if key.starts_with('~') {
352 let dest =
353 unwrap_opt_or_return!(dest, Err("Destination required for short verkey".into()));
354 let mut result = base58::decode(dest)?;
355 let mut end = base58::decode(&key[1..])?;
356 result.append(&mut end);
357 Ok(Self::new(&base58::encode(result), alg, enc))
358 } else {
359 Ok(Self::new(key, alg, enc))
360 }
361 }
362
363 pub fn long_form(&self) -> String {
364 let mut result = self.key.clone();
365 result.push(':');
366 result.push_str(&self.alg);
367 result
368 }
369
370 pub fn as_base58(self) -> Result<Self, ConversionError> {
371 match self.enc {
372 KeyEncoding::BASE58 => Ok(self),
373 _ => {
374 let key = base58::encode(self.key_bytes()?);
375 Ok(Self::new(
376 key.as_str(),
377 Some(self.alg.clone()),
378 Some(KeyEncoding::BASE58),
379 ))
380 }
381 }
382 }
383
384 pub fn key_bytes(&self) -> Result<Vec<u8>, ConversionError> {
385 match self.enc {
386 KeyEncoding::BASE58 => Ok(base58::decode(&self.key)?),
387 _ => Err("Unsupported verkey encoding".into()),
388 }
389 }
390
391 pub fn encoded_key_bytes(&self) -> &[u8] {
392 self.key.as_bytes()
393 }
394
395 #[cfg(feature = "ed25519")]
396 pub fn key_exchange(&self) -> Result<VerKey, ConversionError> {
397 let vk = self.decode()?;
398 vk.key_exchange()
399 }
400
401 #[cfg(feature = "ed25519")]
402 pub fn key_exchange_encoded(&self) -> Result<Self, ConversionError> {
403 let x_vk = self.key_exchange()?;
404 x_vk.encode(&self.enc)
405 }
406
407 #[cfg(feature = "ed25519")]
408 pub fn verify_signature<M: AsRef<[u8]>, S: AsRef<[u8]>>(
409 &self,
410 message: M,
411 signature: S,
412 ) -> Result<bool, ConversionError> {
413 let vk = self.decode()?;
414 vk.verify_signature(message, signature)
415 }
416}
417
418impl std::fmt::Display for EncodedVerKey {
419 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
420 let out = if self.alg == KeyType::default() {
421 self.key.clone()
422 } else {
423 self.long_form()
424 };
425 f.write_str(out.as_str())
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, &[]).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_eq!(sk.validate().is_ok(), false);
552 let vk = VerKey::new(b"bad key", Some(KeyType::ED25519));
553 assert_eq!(vk.validate().is_ok(), false);
554 }
555}