1use crate::{Address, InternalError, SecretKey, VerifyingKey};
2
3use ed25519_dalek::SigningKey;
4use failure::*;
5
6use std::convert::{TryFrom, TryInto};
7use std::fs;
8use std::path::Path;
9
10pub struct Identity {
13 pub address: Address,
14 pub public_key: VerifyingKey,
15 pub secret_key: Option<SecretKey>,
16}
17
18impl Identity {
19 pub fn read<P: AsRef<Path>>(path: P) -> Fallible<Self> {
21 Identity::try_from(&fs::read_to_string(path)?[..])
22 }
23
24 pub fn read_default() -> Fallible<Self> {
26 Identity::read("/var/lib/zerotier-one/identity.secret")
27 }
28}
29
30impl TryFrom<SecretKey> for Identity {
31 type Error = Error;
32
33 fn try_from(secret_key: SecretKey) -> Fallible<Self> {
34 let public_key = VerifyingKey::from(&secret_key);
35
36 Ok(Self {
37 address: Address::try_from(&public_key)?,
38 public_key: VerifyingKey::from(&secret_key),
39 secret_key: Some(secret_key),
40 })
41 }
42}
43
44impl TryFrom<&str> for Identity {
46 type Error = Error;
47
48 fn try_from(identity: &str) -> Fallible<Self> {
49 let split_identity: Vec<&str> = identity.split(':').collect();
50 let (address1, public_key1, maybe_secret_key1) = match &split_identity[..] {
51 [address, "0", public_key] => (address, public_key, None),
52 [address, "0", public_key, secret_key] => (address, public_key, Some(secret_key)),
53 _ => return Err(InternalError::MalformedIdentity.into()),
54 };
55 let address = Address::try_from(hex::decode(address1)?.as_slice())?;
56 let public_key = VerifyingKey::try_from(hex::decode(public_key1)?.as_slice())?;
57 let secret_key = match maybe_secret_key1 {
58 Some(secret_key) => Some(SecretKey::try_from(hex::decode(secret_key)?.as_slice())?),
59 None => None,
60 };
61 Ok(Identity {
62 address,
63 public_key,
64 secret_key,
65 })
66 }
67}
68
69impl TryInto<SigningKey> for Identity {
70 type Error = Error;
71
72 fn try_into(self) -> Fallible<SigningKey> {
73 Ok(SigningKey::from_bytes(&self.secret_key.unwrap().ed))
74 }
75}
76
77#[cfg(test)]
78pub mod tests {
79 use ed25519_dalek::{Signer, Verifier};
80
81 use super::*;
82
83 #[test]
84 fn test_identity() -> Fallible<()> {
85 let identity_str = "538c34e03c:0:070288330a72d2aa3cb7935dfe6028d9fb83bdb42240aaa05e33529121babd183ff775351742a47487454195c08c0e83c520e7466fcdde3396a0c4cd40557737:f20542ab6955fe140fb3a5be9557666b9c89a3e2b73432de46d827d11736773aca15c3e03b89a1d09436ae45bc02f84b8d5a0a2f6c0d42b3856c2b22f5ab2b27";
87 let identity = Identity::try_from(identity_str)?;
88
89 let secret_key = identity.secret_key.unwrap();
92 let public_key = identity.public_key.clone();
93
94 assert_eq!(identity.public_key.ed, public_key.ed);
95 assert_eq!(identity.public_key.dh.as_bytes(), public_key.dh.as_bytes());
96
97 let keypair = ed25519_dalek::SigningKey::from_bytes(&secret_key.ed);
98
99 let message = b"7VbLpreCRY738Sw4OGecCw";
100 let signature = keypair.sign(message);
101
102 identity.public_key.ed.verify(message, &signature)?;
103
104 Ok(())
105 }
106}