indy_utils/keys/
mod.rs

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
22/// Build an encoded verkey
23pub fn build_full_verkey(dest: &str, key: &str) -> Result<EncodedVerKey, ConversionError> {
24    EncodedVerKey::from_str_qualified(key, Some(dest), None, None)
25}
26
27/// A raw signing key used for generating transaction signatures
28#[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/// A raw verkey used in verifying signatures
138#[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/// An encoded verkey appropriate for storing and transmitting
257#[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}