loco-protocol - Loco protocol implementation

Open source Loco protocol implemention made with rust

Specification

Command

| name | size | |-----------|-------------------| | header | (Header) 22 bytes | | data | header.data_size |

Header

| name | size | |-----------|----------| | id | 4 bytes | | status | 2 bytes | | name | 11 bytes | | datatype | 1 bytes | | datasize | 4 bytes |

Secure data

| name | size | |----------------|--------------------| | header | (Header) 20 bytes | | encrypted data | header.size - 16 |

Header

| name | size | |-----------|----------| | iv | 16 bytes | | size | 4 bytes |

Handshake

| name | size | |------------------|------------| | key size | 4 bytes | | keyencrypttype | 4 bytes | | encrypt_type | 4 bytes | | key | 256 bytes |

Note: current implemention only supports RSA-AES

Example

```rust use std::{net::{TcpListener, TcpStream}, thread, io}; use openssl::rsa::Rsa; use loco_protocol::{command::{Command, Error, Header, processor::CommandProcessor}, io::SecureClientStream, io::SecureServerStream, secure::CryptoStore};

fn main() { let key = Rsa::generate(2048).expect("Cannot generate rsa key pairs.");

let socket = TcpListener::bind("127.0.0.1:5022").expect("Cannot bind tcp server");
socket.set_nonblocking(true).expect("Cannot set socket to unblocked mode");

let tcp = TcpStream::connect("127.0.0.1:5022").expect("Cannot connect tcp stream");
tcp.set_nonblocking(true).expect("Cannot set client stream to unblocked mode");

let mut client = CommandProcessor::new(
    SecureClientStream::new(
        CryptoStore::new().unwrap(),
        key.clone(),
        tcp
    )
);

let command = Command {
    header: Header {
        id: 0,
        status: 0,
        name: [72_u8, 101, 108, 108, 111, 0, 0, 0, 0, 0, 0],
        data_type: 0,
        data_size: 5
    },

    data: "Hello".as_bytes().into(),
};

client.write_commmand(command.clone()).expect("Failed to send command");
println!("CLIENT -> {:?}", command.clone());

loop {
    match socket.accept() {

        Ok(connection) => {
            let key = key.clone();

            thread::spawn(move || {
                let mut server = CommandProcessor::new(
                    SecureServerStream::new(
                        CryptoStore::new().unwrap(),
                        key,
                        connection.0
                    )
                );

                println!("Connected from {}", connection.1);
                loop {
                    match server.read_commmand() {

                        Ok(readed) => {
                            if readed.is_some() {
                                let received = readed.unwrap();
                                println!("SERVER <- {:?}", received.clone());

                                server.write_commmand(received.clone()).expect("Command failed to write");
                                println!("SERVER -> {:?}", received.clone());
                                break;
                            }
                        }

                        Err(err) => panic!(format!("{}", err))
                    }
                }
            });
        }

        Err(err) if err.kind() == io::ErrorKind::WouldBlock => {  }

        Err(err) => panic!(format!("{}", err))
    }

    match client.read_commmand() {

        Ok(readed) => {
            match readed {

                Some(received) => {
                    println!("CLIENT <- {:?}", received);
                    return;
                }

                None => {}
            }
        }

        Err(err) => {
            match err {
                Error::Io(io_err) if io_err.kind() == io::ErrorKind::WouldBlock => {}

                _ => panic!(format!("{}", err))
            }
        }
    }
}

} ```

License

loco-protocol is following MIT License.