Skip to content

Commit

Permalink
namespace signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
rob-maron committed Sep 13, 2024
1 parent 115e312 commit 1f53a1a
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 14 deletions.
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"
);
}
}
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 1f53a1a

Please sign in to comment.