ssb_handshake/
lib.rs

1//! Based on Duncan's fantastic
2//! [Scuttlebutt Protocol Guide](https://ssbc.github.io/scuttlebutt-protocol-guide/)
3//! ([repo](https://github.com/ssbc/scuttlebutt-protocol-guide)),
4//! which he graciously released into the public domain.
5#![cfg_attr(not(feature = "std"), no_std)]
6
7mod bytes;
8mod error;
9pub use error::HandshakeError;
10mod crypto;
11
12#[cfg(feature = "std")]
13mod util;
14
15#[cfg(feature = "std")]
16#[path = ""]
17mod std_stuff {
18    mod client;
19    pub use client::client_side;
20    mod server;
21    pub use server::server_side;
22}
23#[cfg(feature = "std")]
24pub use std_stuff::*;
25
26pub mod sync;
27
28#[cfg(all(test, feature = "std"))]
29mod tests {
30    use super::*;
31    use std::io::ErrorKind;
32
33    use futures::executor::block_on;
34    use futures::future::join;
35
36    extern crate async_ringbuffer;
37    use async_ringbuffer::Duplex;
38    use ssb_crypto::{Keypair, NetworkKey, PublicKey};
39
40    #[test]
41    fn basic() {
42        let (mut c_stream, mut s_stream) = Duplex::pair(1024);
43        let skey = Keypair::generate();
44        let ckey = Keypair::generate();
45
46        let net_key = NetworkKey::SSB_MAIN_NET;
47        let client_side = client_side(&mut c_stream, &net_key, &ckey, &skey.public);
48        let server_side = server_side(&mut s_stream, &net_key, &skey);
49
50        let (c_out, s_out) = block_on(async { join(client_side, server_side).await });
51
52        let c_out = c_out.unwrap();
53        let s_out = s_out.unwrap();
54
55        assert_eq!(c_out.write_key.0, s_out.read_key.0);
56        assert_eq!(c_out.read_key.0, s_out.write_key.0);
57
58        assert_eq!(c_out.write_starting_nonce.0, s_out.read_starting_nonce.0);
59        assert_eq!(c_out.read_starting_nonce.0, s_out.write_starting_nonce.0);
60    }
61
62    fn is_eof_err<T>(r: &Result<T, HandshakeError<std::io::Error>>) -> bool {
63        match r {
64            Err(HandshakeError::Io(e)) => e.kind() == ErrorKind::UnexpectedEof,
65            _ => false,
66        }
67    }
68
69    #[test]
70    fn server_rejects_wrong_netkey() {
71        let (mut c_stream, mut s_stream) = Duplex::pair(1024);
72        let skey = Keypair::generate();
73        let ckey = Keypair::generate();
74
75        let cnet = NetworkKey::generate();
76        let snet = NetworkKey::generate();
77
78        let client = client_side(&mut c_stream, &cnet, &ckey, &skey.public);
79        let server = server_side(&mut s_stream, &snet, &skey);
80
81        let (c_out, s_out) = block_on(async { join(client, server).await });
82
83        assert!(is_eof_err(&c_out));
84        match s_out {
85            Err(HandshakeError::ClientHelloVerifyFailed) => {}
86            _ => panic!(),
87        };
88    }
89
90    #[test]
91    fn server_rejects_wrong_pk() {
92        test_handshake_with_bad_server_pk(&PublicKey([0; 32]));
93
94        let key = Keypair::generate();
95        test_handshake_with_bad_server_pk(&key.public);
96    }
97
98    fn test_handshake_with_bad_server_pk(bad_pk: &PublicKey) {
99        let (mut c_stream, mut s_stream) = Duplex::pair(1024);
100        let skey = Keypair::generate();
101        let ckey = Keypair::generate();
102
103        let net_key = NetworkKey::SSB_MAIN_NET;
104
105        let client_side = client_side(&mut c_stream, &net_key, &ckey, &bad_pk);
106        let server_side = server_side(&mut s_stream, &net_key, &skey);
107
108        let (c_out, s_out) = block_on(async { join(client_side, server_side).await });
109
110        assert!(c_out.is_err());
111        assert!(s_out.is_err());
112    }
113}