Skip to content

Commit 006aee6

Browse files
[p2p] Polish (#20)
* add badges * working on security.md * update security * update security * setup READMEs * describe p2p * add all explanations * first stab at description * write features * document ed25519 * add status to rust docs * add network definitions * describe oracle * add note about ping/pongs * define Sender * finish channel definitions * nits * update version * lint last
1 parent c052bed commit 006aee6

15 files changed

+200
-55
lines changed

Cargo.lock

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
1-
# monorepo
1+
# commonware
22

3+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE-MIT)
4+
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE-APACHE)
5+
[![Rust](https://github.com/commonwarexyz/monorepo/actions/workflows/rust.yml/badge.svg)](https://github.com/commonwarexyz/monorepo/actions/workflows/rust.yml)
6+
7+
## Primitives
8+
9+
* [p2p](./p2p/README.md): Communicate with authenticated peers over encrypted connections.
10+
11+
## Examples
12+
13+
_This directory contains examples of how to use various crates in this repository. The code in these examples is often insecure and is not intended to be used in production._
14+
15+
* [chat](./examples/chat/README.md): Send encrypted messages to a group of friends using [commonware-p2p](https://crates.io/crates/commonware-p2p).
316

417
## Licensing
518

SECURITY.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Reporting Security Issues
2+
3+
We welcome security disclosures and are committed to providing prompt attention to any confirmed security issues.
4+
5+
Vulnerabilities should be reported privately [via GitHub Security](https://github.com/commonwarexyz/monorepo/security) instead of as a public issue.
6+
7+
We do not yet offer a bounty program for responsible disclosure of security vulnerabilities, however, we do track contributions and record them on the leaderboard below.
8+
9+
# Leaderboard
10+
11+
1. (Your Name Here)

examples/README.md

-3
This file was deleted.

examples/chat/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ edition = "2021"
44
publish = true
55
version = "0.0.4"
66
license = "MIT OR Apache-2.0"
7-
description = "chat using commonware-p2p"
7+
description = "Send encrypted messages to a group of friends using commonware-p2p."
88
readme = "README.md"
99
homepage = "https://commonware.xyz"
1010
repository = "https://github.com/commonwarexyz/monorepo"

examples/chat/README.md

+34-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,37 @@
1-
# chat
1+
# commonware-chat
2+
3+
[![Crates.io](https://img.shields.io/crates/v/commonware-chat.svg)](https://crates.io/crates/commonware-chat)
4+
5+
Send encrypted messages to a group of friends using [commonware-p2p](https://crates.io/crates/commonware-p2p).
6+
7+
## Usage
8+
9+
### Person 1 (Bootstrapper)
10+
11+
```
12+
cargo run -- --me=1@3001 --allowed_keys=1,2,3,4
13+
```
14+
15+
### Person 2
16+
17+
```
18+
cargo run -- --me=2@3002 --allowed_keys=1,2,3,4 [email protected]:3001
19+
```
20+
21+
### Person 3
22+
23+
```
24+
cargo run -- --me=3@3003 --allowed_keys=1,2,3,4 [email protected]:3001
25+
```
26+
27+
### Person 4 (Different Bootstrapper)
28+
29+
```
30+
cargo run -- --me=4@3004 --allowed_keys=1,2,3,4 [email protected]:3003
31+
```
32+
33+
### Person 5 (Blocked)
234

335
```
4-
cargo run -- --me=1@3000 --allowed_keys=1,2,3,4 --bootstrappers=2@127.0.0.1:3090
36+
cargo run -- --me=5@3005 --allowed_keys=1,2,3,4,5 --bootstrappers=1@127.0.0.1:3001
537
```

examples/chat/src/main.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Send encrypted messages to a group of friends using [commonware-p2p](https://crates.io/crates/commonware-p2p).
2+
13
use clap::{value_parser, Arg, Command};
24
use commonware_p2p::{
35
crypto::{self, Crypto},

p2p/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
name = "commonware-p2p"
33
edition = "2021"
44
publish = true
5-
version = "0.0.4"
5+
version = "0.0.5"
66
license = "MIT OR Apache-2.0"
7-
description = "p2p for blockchains"
7+
description = "Communicate with authenticated peers over encrypted connections."
88
readme = "README.md"
99
homepage = "https://commonware.xyz"
1010
repository = "https://github.com/commonwarexyz/monorepo"

p2p/README.md

+5-28
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,9 @@
1-
# p2p
1+
# commonware-p2p
22

3-
## Disclaimer
3+
[![Crates.io](https://img.shields.io/crates/v/commonware-p2p.svg)](https://crates.io/crates/commonware-p2p)
44

5-
`p2p` is **ALPHA** software and is not yet recommended for production use. Developers should expect breaking changes and occasional instability.
5+
Communicate with authenticated peers over encrypted connections.
66

7-
## Features
7+
## Status
88

9-
* no TLS
10-
* chacha20-poly1305 encryption
11-
* native message chunking
12-
* arbitrary crypto identities
13-
* peer discovery using ordered bit vectors
14-
* fully-connected peers
15-
* configurable rate limiting for each message type
16-
* metrics via prometheus
17-
* message prioritization across channels
18-
* multi-plexing over a single connection
19-
20-
## Components
21-
22-
### Dialer
23-
24-
### Listener
25-
26-
### Tracker
27-
28-
### Spawner
29-
30-
### Peer
31-
32-
### Router
9+
`commonware-p2p` is **ALPHA** software and is not yet recommended for production use. Developers should expect breaking changes and occasional instability.

p2p/src/actors/tracker/ingress.rs

+15
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ impl Mailbox {
9797
}
9898
}
9999

100+
/// Mechanism to register authorized peers.
101+
///
102+
/// Peers that are not explicitly authorized
103+
/// will be blocked by commonware-p2p.
100104
#[derive(Clone)]
101105
pub struct Oracle {
102106
sender: mpsc::Sender<Message>,
@@ -107,6 +111,17 @@ impl Oracle {
107111
Self { sender }
108112
}
109113

114+
/// Register a set of authorized peers at a given index.
115+
///
116+
/// These peer sets are used to construct a bit vector (sorted by public key)
117+
/// to share knowledge about dialable IPs. If a peer does not yet have an index
118+
/// associated with a bit vector, the discovery message will be dropped.
119+
///
120+
/// # Parameters
121+
///
122+
/// * `index` - Index of the set of authorized peers (like a blockchain height).
123+
/// Should be monotonically increasing.
124+
/// * `peers` - Vector of authorized peers at an `index` (does not need to be sorted).
110125
pub async fn register(&self, index: u64, peers: Vec<PublicKey>) {
111126
let _ = self.sender.send(Message::Register { index, peers }).await;
112127
}

p2p/src/channels.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ use governor::Quota;
44
use std::collections::HashMap;
55
use tokio::sync::mpsc;
66

7+
/// Tuple representing a message received from a given public key.
8+
///
9+
/// This message is guranteed to adhere to the configuration of the channel and
10+
/// will already be decrypted and authenticated.
11+
pub type Message = (PublicKey, Bytes);
12+
/// Channel to asynchronously receive messages from a channel.
13+
pub type Receiver = mpsc::Receiver<Message>;
14+
15+
/// Sender is the mechanism used to send arbitrary bytes to
16+
/// a set of recipients over a pre-defined channel.
717
pub struct Sender {
818
channel: u32,
919
messenger: Messenger,
@@ -14,17 +24,21 @@ impl Sender {
1424
Self { channel, messenger }
1525
}
1626

17-
/// priority is over all messages across all channels
27+
/// Sends a message to a set of recipients.
28+
///
29+
/// # Parameters
30+
///
31+
/// * `recipients` - The set of recipients to send the message to.
32+
/// * `message` - The message to send.
33+
/// * `priority` - Whether the message should be sent with priority (across
34+
/// all channels).
1835
pub async fn send(&self, recipients: Vec<PublicKey>, message: Bytes, priority: bool) {
1936
self.messenger
2037
.content(recipients, self.channel, message, priority)
2138
.await;
2239
}
2340
}
2441

25-
pub type Message = (PublicKey, Bytes);
26-
pub type Receiver = mpsc::Receiver<Message>;
27-
2842
#[derive(Clone)]
2943
pub struct Channels {
3044
messenger: Messenger,
@@ -39,7 +53,6 @@ impl Channels {
3953
}
4054
}
4155

42-
/// messages can span multiple frames
4356
pub fn register(
4457
&mut self,
4558
channel: u32,

p2p/src/crypto/ed25519.rs

+24-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
//! Ed25519 implementation of the Crypto trait.
2+
13
use crate::crypto;
24
use ed25519_dalek::{
35
Signature, Signer, SigningKey, Verifier, VerifyingKey, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH,
46
SIGNATURE_LENGTH,
57
};
68
use sha2::{Digest, Sha256};
79

10+
const MESSAGE_PREFIX: &str = "commonware-p2p";
11+
12+
/// Ed25519 Signer.
813
#[derive(Clone)]
914
pub struct Ed25519 {
1015
signer: SigningKey,
@@ -19,6 +24,12 @@ impl Ed25519 {
1924
verifier: verifier.to_bytes().to_vec().into(),
2025
}
2126
}
27+
28+
fn payload(message: Vec<u8>) -> Vec<u8> {
29+
let mut payload = Vec::from(MESSAGE_PREFIX.as_bytes());
30+
payload.extend_from_slice(&message);
31+
payload
32+
}
2233
}
2334

2435
impl crypto::Crypto for Ed25519 {
@@ -27,7 +38,8 @@ impl crypto::Crypto for Ed25519 {
2738
}
2839

2940
fn sign(&mut self, message: Vec<u8>) -> crypto::Signature {
30-
self.signer.sign(&message).to_bytes().to_vec().into()
41+
let payload = Self::payload(message);
42+
self.signer.sign(&payload).to_bytes().to_vec().into()
3143
}
3244

3345
fn validate(public_key: &crypto::PublicKey) -> bool {
@@ -56,11 +68,19 @@ impl crypto::Crypto for Ed25519 {
5668
Err(_) => return false,
5769
};
5870
let signature = Signature::from(signature);
59-
public_key.verify(&message, &signature).is_ok()
71+
let payload = Self::payload(message);
72+
public_key.verify(&payload, &signature).is_ok()
6073
}
6174
}
6275

63-
pub fn insecure_signer(peer: u16) -> Ed25519 {
64-
let secret_key: [u8; SECRET_KEY_LENGTH] = Sha256::digest(peer.to_be_bytes()).into();
76+
/// Creates a new Ed25519 signer with a secret key derived from the provided
77+
/// seed.
78+
///
79+
/// # Warning
80+
///
81+
/// This function is intended for testing and demonstration purposes only.
82+
/// It should never be used in production.
83+
pub fn insecure_signer(seed: u16) -> Ed25519 {
84+
let secret_key: [u8; SECRET_KEY_LENGTH] = Sha256::digest(seed.to_be_bytes()).into();
6585
Ed25519::new(SigningKey::from(secret_key))
6686
}

p2p/src/crypto/mod.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
1-
//! TODO
1+
//! Cryptographic definitions required by commonware-p2p and select implementations
2+
//! of different PKI schemes.
23
34
use bytes::Bytes;
45

56
pub mod ed25519;
67

8+
/// Byte array representing an arbitrary public key.
79
pub type PublicKey = Bytes;
10+
/// Byte array representing an arbitrary signature.
811
pub type Signature = Bytes;
912

13+
/// Cryptographic operations required by commonware-p2p.
14+
///
15+
/// # Warning
16+
///
17+
/// Although data provided to this implementation to be signed are expected to be
18+
/// unique to commonware-p2p, it is strongly recommended to prefix any payloads
19+
/// with a unique identifier to prevent replay attacks.
1020
pub trait Crypto: Send + Sync + Clone + 'static {
21+
/// Returns the public key of the signer.
1122
fn me(&self) -> PublicKey;
23+
/// Sign the given data (usually an IP).
1224
fn sign(&mut self, data: Vec<u8>) -> Signature;
13-
25+
/// Verify that a public key is well-formatted.
1426
fn validate(public_key: &PublicKey) -> bool;
27+
/// Check that a signature is valid for the given data and public key.
1528
fn verify(data: Vec<u8>, public_key: &PublicKey, signature: &Signature) -> bool;
1629
}

p2p/src/lib.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,29 @@
1-
//! Fully-connected ...
1+
//! Communicate with authenticated peers over encrypted connections.
22
//!
3-
//! TODO: Add more documentation here
3+
//! commonware-p2p provides encrypted, multiplexed communication between fully-connected peers
4+
//! identified by a developer-specified cryptographic identity (i.e. BLS, ed25519, etc.). Unlike
5+
//! most p2p crates, commonware-p2p implements its own encrypted transport layer (no TLS) that
6+
//! exclusively uses said cryptographic identities to authenticate incoming connections (dropping
7+
//! any that aren't explicitly authorized). Peer discovery occurs automatically using ordered bit
8+
//! vectors (sorted by authorized cryptographic identities) to efficiently communicate knowledge
9+
//! of dialable peers.
10+
//!
11+
//! # Status
12+
//!
13+
//! `commonware-p2p` is **ALPHA** software and is not yet recommended for production use. Developers should
14+
//! expect breaking changes and occasional instability.
15+
//!
16+
//! # Features
17+
//!
18+
//! * No TLS, No X.509 Certificates, No Protocol Negotiation
19+
//! * ChaCha20-Poly1305 Stream Encryption
20+
//! * Arbitrary Cryptographic Peer Identities
21+
//! * Automatic Peer Discovery Using Bit Vectors (Used as Ping/Pongs)
22+
//! * Multiplexing With Configurable Rate Limiting Per Channel and Send Prioritization
23+
//! * Emebdded Message Chunking
24+
//! * Metrics via Prometheus
25+
//!
26+
//! # Example
427
//!
528
//! ```rust
629
//! use commonware_p2p::{

0 commit comments

Comments
 (0)