Skip to main content

tentacle_secio/
lib.rs

1//! Aes Encrypted communication and handshake process implementation
2
3#![deny(missing_docs)]
4use rand::RngCore;
5
6pub use crate::{handshake::handshake_struct::PublicKey, peer_id::PeerId};
7
8/// Encrypted and decrypted codec implementation, and stream handle
9pub mod codec;
10/// Symmetric ciphers algorithms
11pub mod crypto;
12mod dh_compat;
13/// Error type
14pub mod error;
15/// Implementation of the handshake process
16pub mod handshake;
17/// Peer id
18pub mod peer_id;
19/// A little encapsulation of secp256k1
20mod secp256k1_compat;
21mod sha256_compat;
22/// Supported algorithms
23mod support;
24
25/// Public key generated temporarily during the handshake
26pub type EphemeralPublicKey = Vec<u8>;
27
28/// Key pair of asymmetric encryption algorithm
29#[derive(Clone, Debug)]
30pub struct SecioKeyPair {
31    inner: KeyPairInner,
32}
33
34impl SecioKeyPair {
35    /// Generates a new random sec256k1 key pair.
36    pub fn secp256k1_generated() -> SecioKeyPair {
37        loop {
38            let mut key = [0; crate::secp256k1_compat::SECRET_KEY_SIZE];
39            rand::thread_rng().fill_bytes(&mut key);
40            if let Ok(private) = crate::secp256k1_compat::secret_key_from_slice(&key) {
41                return SecioKeyPair {
42                    inner: KeyPairInner::Secp256k1 { private },
43                };
44            }
45        }
46    }
47
48    /// Builds a `SecioKeyPair` from a raw secp256k1 32 bytes private key.
49    pub fn secp256k1_raw_key<K>(key: K) -> Result<SecioKeyPair, error::SecioError>
50    where
51        K: AsRef<[u8]>,
52    {
53        let private = crate::secp256k1_compat::secret_key_from_slice(key.as_ref())
54            .map_err(|_| error::SecioError::SecretGenerationFailed)?;
55
56        Ok(SecioKeyPair {
57            inner: KeyPairInner::Secp256k1 { private },
58        })
59    }
60
61    /// Returns the public key corresponding to this key pair.
62    pub fn public_key(&self) -> PublicKey {
63        match self.inner {
64            KeyPairInner::Secp256k1 { ref private } => {
65                let pubkey = crate::secp256k1_compat::from_secret_key(private);
66                PublicKey {
67                    key: crate::secp256k1_compat::serialize_pubkey(&pubkey),
68                }
69            }
70        }
71    }
72
73    /// Generate Peer id
74    pub fn peer_id(&self) -> PeerId {
75        self.public_key().peer_id()
76    }
77}
78
79#[derive(Clone)]
80enum KeyPairInner {
81    Secp256k1 {
82        private: crate::secp256k1_compat::SecretKey,
83    },
84}
85
86impl std::fmt::Debug for KeyPairInner {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88        f.debug_struct("KeyPair").finish()
89    }
90}
91
92/// Possible digest algorithms.
93#[derive(Copy, Clone, Debug, PartialEq, Eq)]
94pub enum Digest {
95    /// Sha256 digest
96    Sha256,
97    /// Sha512 digest
98    Sha512,
99}
100
101impl Digest {
102    /// Returns the size in bytes of a digest of this kind.
103    #[inline]
104    pub fn num_bytes(self) -> usize {
105        match self {
106            Digest::Sha256 => 256 / 8,
107            Digest::Sha512 => 512 / 8,
108        }
109    }
110}
111
112/// KeyProvider on ecdh procedure
113#[cfg_attr(feature = "async-sign", async_trait::async_trait)]
114pub trait KeyProvider: std::clone::Clone + Send + Sync + 'static {
115    /// Error
116    type Error: Into<crate::error::SecioError>;
117
118    /// Constructs a signature for `msg` using the secret key `sk`
119    #[cfg(feature = "async-sign")]
120    async fn sign_ecdsa_async<T: AsRef<[u8]> + Send>(
121        &self,
122        message: T,
123    ) -> Result<Vec<u8>, Self::Error> {
124        self.sign_ecdsa(message)
125    }
126
127    /// Constructs a signature for `msg` using the secret key `sk`
128    fn sign_ecdsa<T: AsRef<[u8]>>(&self, message: T) -> Result<Vec<u8>, Self::Error>;
129
130    /// Creates a new public key from the [`KeyProvider`].
131    fn pubkey(&self) -> Vec<u8>;
132
133    /// Checks that `sig` is a valid ECDSA signature for `msg` using the pubkey.
134    fn verify_ecdsa<P, T, F>(&self, pubkey: P, message: T, signature: F) -> bool
135    where
136        P: AsRef<[u8]>,
137        T: AsRef<[u8]>,
138        F: AsRef<[u8]>;
139}
140
141impl KeyProvider for SecioKeyPair {
142    type Error = error::SecioError;
143
144    fn sign_ecdsa<T: AsRef<[u8]>>(&self, message: T) -> Result<Vec<u8>, Self::Error> {
145        let msg = match crate::secp256k1_compat::message_from_slice(message.as_ref()) {
146            Ok(m) => m,
147            Err(_) => {
148                log::debug!("message has wrong format");
149                return Err(error::SecioError::InvalidMessage);
150            }
151        };
152        let signature = match self.inner {
153            KeyPairInner::Secp256k1 { ref private } => crate::secp256k1_compat::sign(&msg, private),
154        };
155
156        Ok(crate::secp256k1_compat::signature_to_vec(signature))
157    }
158
159    fn pubkey(&self) -> Vec<u8> {
160        match self.inner {
161            KeyPairInner::Secp256k1 { ref private } => crate::secp256k1_compat::serialize_pubkey(
162                &crate::secp256k1_compat::from_secret_key(private),
163            ),
164        }
165    }
166
167    fn verify_ecdsa<P, T, F>(&self, pubkey: P, message: T, signature: F) -> bool
168    where
169        P: AsRef<[u8]>,
170        T: AsRef<[u8]>,
171        F: AsRef<[u8]>,
172    {
173        let signature = crate::secp256k1_compat::signature_from_der(signature.as_ref());
174        let msg = crate::secp256k1_compat::message_from_slice(message.as_ref());
175        let pubkey = crate::secp256k1_compat::pubkey_from_slice(pubkey.as_ref());
176
177        if let (Ok(signature), Ok(message), Ok(pubkey)) = (signature, msg, pubkey) {
178            if !crate::secp256k1_compat::verify(&message, &signature, &pubkey) {
179                log::debug!("failed to verify the remote's signature");
180                return false;
181            }
182        } else {
183            log::debug!("remote's secp256k1 signature has wrong format");
184            return false;
185        }
186        true
187    }
188}
189/// Empty key provider
190#[derive(Debug, Clone)]
191pub struct NoopKeyProvider;
192
193impl KeyProvider for NoopKeyProvider {
194    type Error = error::SecioError;
195
196    fn sign_ecdsa<T: AsRef<[u8]>>(&self, _message: T) -> Result<Vec<u8>, Self::Error> {
197        Err(error::SecioError::NotSupportKeyProvider)
198    }
199
200    fn pubkey(&self) -> Vec<u8> {
201        Vec::new()
202    }
203
204    fn verify_ecdsa<P, T, F>(&self, _pubkey: P, _message: T, _signature: F) -> bool
205    where
206        P: AsRef<[u8]>,
207        T: AsRef<[u8]>,
208        F: AsRef<[u8]>,
209    {
210        false
211    }
212}