1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use crate::error::{Code, Error};
use chain_crypto::{Ed25519, KeyPair, PublicKey, SecretKey, Signature, Verification};
use rand_core::{CryptoRng, RngCore};

use std::fmt;
use std::net::SocketAddr;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Peer {
    addr: SocketAddr,
}

impl Peer {
    #[inline]
    pub fn addr(&self) -> SocketAddr {
        self.addr
    }
}

impl From<SocketAddr> for Peer {
    #[inline]
    fn from(addr: SocketAddr) -> Self {
        Peer { addr }
    }
}

impl fmt::Display for Peer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.addr)
    }
}

/// The key pair used to authenticate a network node,
/// including the secret key.
#[derive(Clone, Debug)]
pub struct NodeKeyPair(KeyPair<Ed25519>);

impl NodeKeyPair {
    /// Generates a key pair using the provided random number generator.
    pub fn generate<R: RngCore + CryptoRng>(rng: R) -> Self {
        NodeKeyPair(KeyPair::generate(rng))
    }

    /// Produces the node ID (i.e. the public key), authenticated by signing
    /// the provided nonce with the secret key.
    pub fn sign(&self, nonce: &[u8]) -> AuthenticatedNodeId {
        let signature = self.0.private_key().sign(nonce);
        AuthenticatedNodeId {
            id: NodeId(self.0.public_key().clone()),
            signature,
        }
    }
}

impl From<SecretKey<Ed25519>> for NodeKeyPair {
    fn from(key: SecretKey<Ed25519>) -> Self {
        Self(key.into())
    }
}

/// Identifier of a network peer.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct NodeId(PublicKey<Ed25519>);

impl NodeId {
    #[inline]
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_ref()
    }

    /// Adds a signature given as a byte slice to produce an
    /// `AuthenticatedNodeId`.
    ///
    /// # Errors
    ///
    /// Returns an error if `signature` byte slice does not conform to the
    /// format of a signature used to authenticate node ID.
    pub fn authenticated(self, signature: &[u8]) -> Result<AuthenticatedNodeId, Error> {
        let signature =
            Signature::from_binary(signature).map_err(|e| Error::new(Code::InvalidArgument, e))?;
        Ok(AuthenticatedNodeId {
            id: self,
            signature,
        })
    }
}

impl TryFrom<&[u8]> for NodeId {
    type Error = Error;

    fn try_from(src: &[u8]) -> Result<Self, Error> {
        match PublicKey::from_binary(src) {
            Ok(data) => Ok(NodeId(data)),
            Err(e) => Err(Error::new(Code::InvalidArgument, e)),
        }
    }
}

/// A node ID accompanied with a signature.
///
/// The signature is not assumed to be valid by construction.
/// Use the `verify` method to verify the signature against the original
/// nonce.
pub struct AuthenticatedNodeId {
    id: NodeId,
    signature: Signature<[u8], Ed25519>,
}

impl AuthenticatedNodeId {
    pub fn id(&self) -> &NodeId {
        &self.id
    }

    pub fn signature(&self) -> &[u8] {
        self.signature.as_ref()
    }

    /// Verifies that the signature is correct for this node ID and
    /// the given nonce.
    pub fn verify(&self, nonce: &[u8]) -> Result<(), Error> {
        match self.signature.verify(&self.id.0, nonce) {
            Verification::Success => Ok(()),
            Verification::Failed => Err(Error::new(
                Code::InvalidArgument,
                "invalid node ID signature",
            )),
        }
    }
}

impl From<AuthenticatedNodeId> for NodeId {
    fn from(auth: AuthenticatedNodeId) -> Self {
        auth.id
    }
}