kuska means together in Runasimi
kuska is an implementation of decentralized social network Secure Scuttlebut written in rust, it does not aim to provide a user interface and the functionality implemented in some clients like Patchwork, Patchbay, but the full set of libraries to be able to develop applications for the secure scuttlebut network.
kuska-handshake is the implementation of the handhake and box stream used in SSB, detailed information about the protocol can be found in https://ssbc.github.io/scuttlebutt-protocol-guide/.
the current implementation contains:
- an agnostic implementation of the protcol using sodiumoxide
- a synchronous version (needs
sync
feature) - an asynchronous
async_std
version (needsasync_std
feature, with wrappers fortokio
withtokio_compat
feature)
Create the server key pair
let (pk, sk) = ed25519::gen_keypair();
let pk_b64 = base64::encode_config(&pk, base64::STANDARD);
Define the network to connect
let net_id_hex = "d4a1cb88a66f02f8db635ce26441cc5dac1b08420ceaac230839b755845a9ffb";
let net_id = auth::Key::from_slice(&hex::decode(net_id_hex).unwrap()).unwrap();
Listen, accept the socket, and perform the handshake
let listener = TcpListener::bind(...).unwrap();
let (socket, addr) = listener.accept().unwrap();
let handshake = handshake_server(&socket, net_id, pk, sk)?;
Once the handshake is performed, create both box streams, one to send and another to recieve data,
those box streams implements std::io::Read
and std::io::Write
to perform usual i/o operations on them.
let (key_nonce_send, key_nonce_recv) = KeyNonce::from_handshake(handshake);
let (mut box_stream_read, mut box_stream_write) =
BoxStream::new(&socket, &socket, key_nonce_send, key_nonce_recv).split_read_write();
box_stream_read.read_exact(...)
box_stream_write.write_all(...)
Create the client key pair
let (pk, sk) = ed25519::gen_keypair();
let pk_b64 = base64::encode_config(&pk, base64::STANDARD);
Connect to the server, perform the handshake (you need the server public key), and create the box streams to communicate
let socket = TcpStream::connect(...).unwrap();
let handshake = handshake_client(&socket, net_id, pk, sk, server_pk)?;
let (key_nonce_send, key_nonce_recv) = KeyNonce::from_handshake(handshake);
let (mut box_stream_read, mut box_stream_write) =
BoxStream::new(&socket, &socket, key_nonce_send, key_nonce_recv).split_read_write();
box_stream_read.read_exact(...)
box_stream_write.write_all(...)
The async_std
client is analogous to the sync
version, just all functions are async and uses async_std::io::Read
and async_std::io::Write
for box streams
use async_std::io::{Read,Write};
use async_std::net::TcpStream;
use kuska_handshake::async_std::{handshake_client,BoxStream};
#[async_std::main]
async fn main() -> Result<T, Box<dyn Error>> {
...
let mut socket = TcpStream::connect("127.0.0.1:8008").await?;
let (_,handshake) = handshake_client(&mut socket, ssb_net_id(), pk, sk, server_pk).await?;
let (box_stream_read, box_stream_write) =
BoxStream::from_handhake(&socket, &socket, handshake, 0x8000)
.split_read_write();
To use the tokio you need the wrappers used in kuska_handshake::async_std::tokio_compat
:
use tokio::net::TcpStream;
use kuska_handshake::async_std::{BoxStream,handshake_client,TokioCompatExt,TokioCompatExtRead,TokioCompatExtWrite};
let tokio_socket : TcpStream = TcpStream::connect("127.0.0.1:8008").await?;
let asyncstd_socket = TokioCompatExt::wrap(tokio_socket);
let (asyncstd_socket,handshake) = handshake_client(asyncstd_socket, ssb_net_id(), pk, sk.clone(), pk).await?;
let mut tokio_socket = asyncstd_socket.into_inner();
let (read,write) = tokio_socket.split();
let read = TokioCompatExtRead::wrap(read);
let write = TokioCompatExtWrite::wrap(write);
let (box_stream_read, box_stream_write) =
BoxStream::from_handhake(read, write, handshake, 0x8000)
.split_read_write();