indy_data_types/keys/
mod.rs

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