Skip to content

Commit

Permalink
Merge pull request #59 from EspressoSystems/breaking
Browse files Browse the repository at this point in the history
Breaking changes
  • Loading branch information
rob-maron authored Oct 18, 2024
2 parents a7523f3 + 9f83f72 commit af42143
Show file tree
Hide file tree
Showing 10 changed files with 365 additions and 278 deletions.
497 changes: 240 additions & 257 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions cdn-broker/src/reexports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod connection {
pub mod protocols {
pub use cdn_proto::connection::protocols::quic::Quic;
pub use cdn_proto::connection::protocols::tcp::Tcp;
pub use cdn_proto::connection::protocols::tcp_tls::TcpTls;
}
}

Expand Down
1 change: 1 addition & 0 deletions cdn-client/src/reexports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod connection {
pub mod protocols {
pub use cdn_proto::connection::protocols::quic::Quic;
pub use cdn_proto::connection::protocols::tcp::Tcp;
pub use cdn_proto::connection::protocols::tcp_tls::TcpTls;
}
}

Expand Down
6 changes: 3 additions & 3 deletions cdn-proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description = "Contains the common protocol definition and common code for the b
[build-dependencies]
rcgen.workspace = true
rustls-pki-types = { version = "1", default-features = false }
capnpc = "0.19"
capnpc = "0.20"

[features]
metrics = ["dep:prometheus"]
Expand All @@ -26,7 +26,7 @@ harness = false


[dependencies]
redis = { version = "0.25", default-features = false, features = [
redis = { version = "0.27", default-features = false, features = [
"connection-manager",
"tokio-comp",
] }
Expand All @@ -44,7 +44,7 @@ lazy_static = { workspace = true }

tokio = { workspace = true }

capnp = "0.19"
capnp = "0.20"
thiserror = "1"
quinn = { version = "0.11", default-features = false, features = [
"rustls",
Expand Down
11 changes: 8 additions & 3 deletions cdn-proto/src/connection/auth/broker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use tracing::error;
use crate::{
bail,
connection::protocols::Connection,
crypto::signature::SignatureScheme,
crypto::signature::{Namespace, SignatureScheme},
def::{PublicKey, RunDef, Scheme},
discovery::{BrokerIdentifier, DiscoveryClient},
error::{Error, Result},
Expand Down Expand Up @@ -169,9 +169,13 @@ impl<R: RunDef> BrokerAuth<R> {
)
.as_secs();

// Sign the timestamp from above
// Sign the timestamp from above (with a namespace)
let signature = bail!(
Scheme::<R::Broker>::sign(&keypair.private_key, &timestamp.to_le_bytes()),
Scheme::<R::Broker>::sign(
&keypair.private_key,
Namespace::BrokerBrokerAuth.as_str(),
&timestamp.to_le_bytes()
),
Crypto,
"failed to sign message"
);
Expand Down Expand Up @@ -261,6 +265,7 @@ impl<R: RunDef> BrokerAuth<R> {
// Verify the signature
if !Scheme::<R::Broker>::verify(
&public_key,
Namespace::BrokerBrokerAuth.as_str(),
&auth_message.timestamp.to_le_bytes(),
&auth_message.signature,
) {
Expand Down
2 changes: 2 additions & 0 deletions cdn-proto/src/connection/auth/marshal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use tracing::error;
use crate::{
bail,
connection::protocols::Connection,
crypto::signature::Namespace,
def::{PublicKey, RunDef, Scheme},
discovery::DiscoveryClient,
error::{Error, Result},
Expand Down Expand Up @@ -64,6 +65,7 @@ impl<R: RunDef> MarshalAuth<R> {
// Verify the signature
if !Scheme::<R::User>::verify(
&public_key,
Namespace::UserMarshalAuth.as_str(),
&auth_message.timestamp.to_le_bytes(),
&auth_message.signature,
) {
Expand Down
8 changes: 6 additions & 2 deletions cdn-proto/src/connection/auth/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use std::{
time::{SystemTime, UNIX_EPOCH},
};

use crate::connection::protocols::Connection;
use crate::crypto::signature::Serializable;
use crate::{
bail,
Expand All @@ -21,6 +20,7 @@ use crate::{
error::{Error, Result},
message::{AuthenticateWithKey, AuthenticateWithPermit, Message, Topic},
};
use crate::{connection::protocols::Connection, crypto::signature::Namespace};

/// This is the `UserAuth` struct that we define methods to for authentication purposes.
pub struct UserAuth<C: ConnectionDef>(PhantomData<C>);
Expand Down Expand Up @@ -48,7 +48,11 @@ impl<C: ConnectionDef> UserAuth<C> {

// Sign the timestamp from above
let signature = bail!(
Scheme::<C>::sign(&keypair.private_key, &timestamp.to_le_bytes()),
Scheme::<C>::sign(
&keypair.private_key,
Namespace::UserMarshalAuth.as_str(),
&timestamp.to_le_bytes()
),
Crypto,
"failed to sign message"
);
Expand Down
104 changes: 97 additions & 7 deletions cdn-proto/src/crypto/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@ use jf_signature::{

use super::rng::DeterministicRng;

/// The auth namespaces for the signature scheme
pub enum Namespace {
UserMarshalAuth,
BrokerBrokerAuth,
}

impl Namespace {
/// Get the namespace as a string
pub fn as_str(&self) -> &'static str {
match self {
Namespace::UserMarshalAuth => "espresso-cdn-user-marshal-auth",
Namespace::BrokerBrokerAuth => "espresso-cdn-broker-broker-auth",
}
}
}

/// This trait defines a generic signature scheme, wherein we can sign and verify messages
/// with the associated public and private keys.
pub trait SignatureScheme: Send + Sync + 'static {
Expand All @@ -27,14 +43,23 @@ pub trait SignatureScheme: Send + Sync + 'static {
///
/// # Errors
/// If signing fails
fn sign(private_key: &Self::PrivateKey, message: &[u8]) -> Result<Vec<u8>>;
fn sign(
private_key: &Self::PrivateKey,
namespace: &'static str,
message: &[u8],
) -> Result<Vec<u8>>;

/// Verify a message with the public key, the message itself, and the signature.
///
/// # Returns
/// - false if verification failed
/// - true if verification succeeded
fn verify(public_key: &Self::PublicKey, message: &[u8], signature: &[u8]) -> bool;
fn verify(
public_key: &Self::PublicKey,
namespace: &'static str,
message: &[u8],
signature: &[u8],
) -> bool;
}

/// Allows for us to be generic over a serializable [signature | public key].
Expand Down Expand Up @@ -96,10 +121,22 @@ impl SignatureScheme for BLS {
/// # Errors
/// - If serialization fails
/// - If signing fails
fn sign(private_key: &Self::PrivateKey, message: &[u8]) -> Result<Vec<u8>> {
fn sign(
private_key: &Self::PrivateKey,
namespace: &'static str,
message: &[u8],
) -> Result<Vec<u8>> {
// Add the namespace to the message
let mut namespaced_message = namespace.as_bytes().to_vec();
namespaced_message.extend_from_slice(message);

// Sign the message
let serialized_signature =
<Self as JfSignatureScheme>::sign(&(), private_key, message, &mut DeterministicRng(0))?;
let serialized_signature = <Self as JfSignatureScheme>::sign(
&(),
private_key,
namespaced_message,
&mut DeterministicRng(0),
)?;

// Serialize the signature
let mut buf = vec![];
Expand All @@ -115,7 +152,16 @@ impl SignatureScheme for BLS {
/// # Errors
/// - If signature deserialization fails
/// - If signing fails
fn verify(public_key: &Self::PublicKey, message: &[u8], signature: &[u8]) -> bool {
fn verify(
public_key: &Self::PublicKey,
namespace: &'static str,
message: &[u8],
signature: &[u8],
) -> bool {
// Add the namespace to the message
let mut namespaced_message = namespace.as_bytes().to_vec();
namespaced_message.extend_from_slice(message);

// Deserialize the signature
let Ok(signature) =
<Self as JfSignatureScheme>::Signature::deserialize_uncompressed(signature)
Expand All @@ -124,6 +170,50 @@ impl SignatureScheme for BLS {
};

// Verify the signature
<Self as JfSignatureScheme>::verify(&(), public_key, message, &signature).is_ok()
<Self as JfSignatureScheme>::verify(&(), public_key, namespaced_message, &signature).is_ok()
}
}

#[cfg(test)]
mod test {
use rand::{rngs::StdRng, SeedableRng};

use super::*;

#[test]
fn signature_namespace_parity() {
// Generate a keypair
let keypair =
BLS::key_gen(&(), &mut StdRng::seed_from_u64(0)).expect("failed to generate key");

// Sign a message with the namespace `UserMarshalAuth`
let signature = <BLS as SignatureScheme>::sign(
&keypair.0,
crate::crypto::signature::Namespace::UserMarshalAuth.as_str(),
b"hello world",
)
.expect("failed to sign message");

// Verify the signature with the namespace `UserMarshalAuth`
assert!(
<BLS as SignatureScheme>::verify(
&keypair.1,
crate::crypto::signature::Namespace::UserMarshalAuth.as_str(),
b"hello world",
&signature,
),
"failed to verify signature"
);

// Make sure it fails with the wrong namespace
assert!(
!<BLS as SignatureScheme>::verify(
&keypair.1,
crate::crypto::signature::Namespace::BrokerBrokerAuth.as_str(),
b"hello world",
&signature,
),
"verified signature with wrong namespace"
);
}
}
9 changes: 5 additions & 4 deletions cdn-proto/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use std::marker::PhantomData;
use jf_signature::bls_over_bn254::BLSOverBN254CurveSignatureScheme as BLS;
use num_enum::{IntoPrimitive, TryFromPrimitive};

use crate::connection::protocols::{quic::Quic, tcp::Tcp, Protocol as ProtocolType};
use crate::connection::protocols::tcp_tls::TcpTls;
use crate::connection::protocols::{tcp::Tcp, Protocol as ProtocolType};
use crate::crypto::signature::SignatureScheme;
use crate::discovery::embedded::Embedded;
use crate::discovery::{redis::Redis, DiscoveryClient};
Expand Down Expand Up @@ -111,16 +112,16 @@ impl ConnectionDef for ProductionBrokerConnection {
}

/// The production user connection configuration.
/// Uses BLS signatures and QUIC.
/// Uses BLS signatures and TCP+TLS.
pub struct ProductionUserConnection;
impl ConnectionDef for ProductionUserConnection {
type Scheme = BLS;
type Protocol = Quic;
type Protocol = TcpTls;
type MessageHook = NoMessageHook;
}

/// The production client connection configuration.
/// Uses BLS signatures and QUIC.
/// Uses BLS signatures and TCP+TLS.
/// Differs from `ProductionUserConnection` in that this is used by
/// the client, not the broker.
pub struct ProductionClientConnection;
Expand Down
4 changes: 2 additions & 2 deletions cdn-proto/src/discovery/redis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl DiscoveryClient for Redis {
// Get the number of connections the broker has
let num_connections: u64 = bail!(
redis::cmd("GET")
.arg(&format!("{broker}/num_connections"))
.arg(format!("{broker}/num_connections"))
.query_async(&mut self.underlying_connection)
.await,
Connection,
Expand All @@ -152,7 +152,7 @@ impl DiscoveryClient for Redis {
// Get the number of permits the broker has
let num_permits: u64 = bail!(
redis::cmd("SCARD")
.arg(&format!("{broker}/permits"))
.arg(format!("{broker}/permits"))
.query_async(&mut self.underlying_connection)
.await,
Connection,
Expand Down

0 comments on commit af42143

Please sign in to comment.