zerotier_api/
public_key.rs

1use crate::{InternalError, SecretKey};
2
3use arrayref::array_ref;
4use ed25519_dalek::SigningKey;
5use failure::Error;
6use std::convert::{TryFrom, TryInto};
7
8/// [`VerifyingKey`](struct.VerifyingKey.html) length in bytes.
9pub const PUBLIC_KEY_LENGTH: usize = 64;
10
11/// Concatenation of X25519 public key (first 32 bytes) and Ed25519 public key (last 32 bytes).
12#[derive(Clone, Debug)]
13pub struct VerifyingKey {
14    /// Ed25519 public key (last 32 bytes)
15    pub ed: ed25519_dalek::VerifyingKey,
16    /// X25519 public key (first 32 bytes)
17    pub dh: x25519_dalek::PublicKey,
18}
19
20/// Derive public key from secret key.
21impl From<&SecretKey> for VerifyingKey {
22    fn from(secret_key: &SecretKey) -> Self {
23        // Create a SigningKey (SecretKey) from the bytes
24        let signing_key: SigningKey = SigningKey::from_bytes(&secret_key.ed);
25
26        Self {
27            ed: signing_key.verifying_key(),
28            dh: x25519_dalek::PublicKey::from(&secret_key.dh),
29        }
30    }
31}
32
33/// Construct a public key from a slice of bytes, fails if `len(bytes) != 64`.
34impl TryFrom<&[u8]> for VerifyingKey {
35    type Error = Error;
36
37    fn try_from(bytes: &[u8]) -> Result<Self, Error> {
38        if bytes.len() != PUBLIC_KEY_LENGTH {
39            Err(InternalError::BytesLengthError.into())
40        } else {
41            Ok(Self {
42                ed: ed25519_dalek::VerifyingKey::from_bytes(&bytes[32..].try_into()?)?,
43                dh: x25519_dalek::PublicKey::from(*array_ref!(bytes, 0, 32)),
44            })
45        }
46    }
47}
48
49/// Convert this public key into a byte array.
50impl Into<[u8; PUBLIC_KEY_LENGTH]> for &VerifyingKey {
51    fn into(self) -> [u8; PUBLIC_KEY_LENGTH] {
52        let mut buf = [0u8; PUBLIC_KEY_LENGTH];
53
54        buf[..32].copy_from_slice(self.dh.as_bytes());
55        buf[32..].copy_from_slice(self.ed.as_bytes());
56        buf
57    }
58}