Skip to content

Commit

Permalink
feat: integrate AuthDecode
Browse files Browse the repository at this point in the history
  • Loading branch information
themighty1 committed Oct 10, 2024
1 parent 61ff3a8 commit e90159f
Show file tree
Hide file tree
Showing 37 changed files with 1,544 additions and 139 deletions.
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ members = [
"crates/benches",
"crates/common",
"crates/components/aead",
"crates/components/authdecode/authdecode",
"crates/components/authdecode/authdecode-core",
"crates/components/authdecode/single-range",
"crates/components/block-cipher",
"crates/components/hmac-sha256",
"crates/components/hmac-sha256-circuits",
"crates/components/key-exchange",
"crates/components/poseidon-halo2",
"crates/components/stream-cipher",
"crates/components/universal-hash",
"crates/core",
Expand Down Expand Up @@ -39,6 +43,10 @@ opt-level = 1
[workspace.dependencies]
notary-client = { path = "crates/notary/client" }
notary-server = { path = "crates/notary/server" }
poseidon-halo2 = { path = "crates/components/poseidon-halo2" }
tlsn-authdecode = { path = "crates/components/authdecode/authdecode" }
tlsn-authdecode-core = { path = "crates/components/authdecode/authdecode-core" }
tlsn-authdecode-single-range = { path = "crates/components/authdecode/single-range" }
tls-server-fixture = { path = "crates/tls/server-fixture" }
tlsn-aead = { path = "crates/components/aead" }
tlsn-block-cipher = { path = "crates/components/block-cipher" }
Expand Down
3 changes: 3 additions & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ edition = "2021"

[features]
default = []
# Enables common types and config parameters used in the AuthDecode protocol.
# This feature can only be used if the prover and the verifier enable their `authdecode_unsafe` feature.
authdecode_unsafe_common = []

[dependencies]
tlsn-core = { workspace = true }
Expand Down
45 changes: 41 additions & 4 deletions crates/common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ pub struct ProtocolConfig {
max_recv_data_online: usize,
/// Maximum number of bytes that can be received.
max_recv_data: usize,
#[cfg(feature = "authdecode_unsafe_common")]
/// Maximum number of bytes which can be committed to using a zk-friendly hash.
#[builder(default = "0")]
max_zk_friendly_hash_data: usize,
/// Version that is being run by prover/verifier.
#[builder(setter(skip), default = "VERSION.clone()")]
version: Version,
Expand Down Expand Up @@ -72,6 +76,12 @@ impl ProtocolConfig {
self.max_recv_data
}

#[cfg(feature = "authdecode_unsafe_common")]
/// Returns the maximum number of bytes for which a zk-friendly hash commitment can be computed.
pub fn max_zk_friendly_hash_data(&self) -> usize {
self.max_zk_friendly_hash_data
}

/// Returns OT sender setup count.
pub fn ot_sender_setup_count(&self, role: Role) -> usize {
ot_send_estimate(
Expand Down Expand Up @@ -101,6 +111,10 @@ pub struct ProtocolConfigValidator {
max_sent_data: usize,
/// Maximum number of bytes that can be received.
max_recv_data: usize,
/// Maximum number of bytes for which a zk-friendly hash commitment can be computed.
#[builder(default = "0")]
#[cfg(feature = "authdecode_unsafe_common")]
max_zk_friendly_hash_data: usize,
/// Version that is being run by checker.
#[builder(setter(skip), default = "VERSION.clone()")]
version: Version,
Expand All @@ -122,10 +136,17 @@ impl ProtocolConfigValidator {
self.max_recv_data
}

/// Performs compatibility check of the protocol configuration between
/// prover and verifier.
#[cfg(feature = "authdecode_unsafe_common")]
/// Returns the maximum number of bytes for which a zk-friendly hash commitment can be computed.
pub fn max_zk_friendly_hash_data(&self) -> usize {
self.max_zk_friendly_hash_data
}

/// Performs compatibility check of the protocol configuration between prover and verifier.
pub fn validate(&self, config: &ProtocolConfig) -> Result<(), ProtocolConfigError> {
self.check_max_transcript_size(config.max_sent_data, config.max_recv_data)?;
#[cfg(feature = "authdecode_unsafe_common")]
self.check_max_zk_friendly_hash_data(config.max_zk_friendly_hash_data)?;
self.check_version(&config.version)?;
Ok(())
}
Expand Down Expand Up @@ -153,8 +174,24 @@ impl ProtocolConfigValidator {
Ok(())
}

// Checks if both versions are the same (might support check for different but
// compatible versions in the future).
#[cfg(feature = "authdecode_unsafe_common")]
// Checks if the number of bytes for zk-friendly hashes is within limits.
fn check_max_zk_friendly_hash_data(
&self,
max_zk_friendly_hash_data: usize,
) -> Result<(), ProtocolConfigError> {
if max_zk_friendly_hash_data > self.max_zk_friendly_hash_data {
return Err(ProtocolConfigError::version(format!(
"max_zk_friendly_hash_data {:?} is greater than the configured limit {:?}",
max_zk_friendly_hash_data, self.max_zk_friendly_hash_data
)));
}

Ok(())
}

// Checks if both versions are the same (might support check for different but compatible versions
// in the future).
fn check_version(&self, peer_version: &Version) -> Result<(), ProtocolConfigError> {
if *peer_version != self.version {
return Err(ProtocolConfigError::version(format!(
Expand Down
22 changes: 22 additions & 0 deletions crates/components/authdecode/single-range/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "tlsn-authdecode-single-range"
authors = ["TLSNotary Team"]
description = "A convenience type for using AuthDecode with data contained in a single range of bytes"
keywords = ["tls", "mpc", "2pc"]
categories = ["cryptography"]
license = "MIT OR Apache-2.0"
version = "0.1.0"
edition = "2021"

[lib]
name = "authdecode_single_range"

[dependencies]
tlsn-authdecode-core = { workspace = true }
tlsn-core = { workspace = true, features = ["use_poseidon_halo2"] }
mpz-circuits = { workspace = true }
mpz-garble-core = { workspace = true }
mpz-core = { workspace = true }

getset = "0.1.2"
serde = { workspace = true }
152 changes: 152 additions & 0 deletions crates/components/authdecode/single-range/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
//! A convenience type for using AuthDecode with the halo2 backend for a single byterange of a TLS
//! transcript data. The length of the data must not exceed the maximum chunk size allowed by the
//! backend.
use core::ops::Range;
use getset::Getters;
use mpz_circuits::types::ValueType;
use mpz_core::{utils::blake3, Block};
use mpz_garble_core::ChaChaEncoder;
use serde::{Deserialize, Serialize};
use tlsn_core::transcript::{Direction, RX_TRANSCRIPT_ID, TX_TRANSCRIPT_ID};

use authdecode_core::{
backend::halo2::CHUNK_SIZE,
encodings::{Encoding, EncodingProvider, EncodingProviderError, FullEncodings},
id::{Id, IdCollection},
SSP,
};

#[derive(Clone, PartialEq, Serialize, Deserialize, Getters)]
/// A single byterange of data with the corresponding direction. The data is treated as a big-endian
/// byte string with MSB0 bit ordering.
pub struct SingleRange {
/// The direction in which the data was transmitted.
#[getset(get = "pub")]
direction: Direction,
/// A range of bytes.
#[getset(get = "pub")]
range: Range<usize>,
}

impl SingleRange {
/// Creates a new `SingleRange`.
///
/// # Panics
///
/// Panics if the range length exceeds the maximim allowed length.
pub fn new(direction: Direction, range: &Range<usize>) -> Self {
assert!(range.len() <= CHUNK_SIZE);

Self {
direction,
range: range.clone(),
}
}
}

impl Default for SingleRange {
fn default() -> Self {
Self {
direction: Direction::Sent,
range: Range::default(),
}
}
}

impl IdCollection for SingleRange {
fn drain_front(&mut self, count: usize) -> Self {
assert!(count % 8 == 0);
assert!(count <= CHUNK_SIZE * 8);
// We will never need to drain since the collection spans a single chunk.
self.clone()
}

fn id(&self, _index: usize) -> Id {
unimplemented!()
}

fn is_empty(&self) -> bool {
self.len() == 0
}

fn len(&self) -> usize {
self.range.len() * 8
}

fn new_from_iter<I: IntoIterator<Item = Self>>(_iter: I) -> Self {
unimplemented!()
}
}

/// An encoder of a TLS transcript.
pub struct TranscriptEncoder {
encoder: ChaChaEncoder,
}

impl TranscriptEncoder {
/// Creates a new encoder from the `seed`.
///
/// # Arguments
///
/// * `seed` - The seed to create the encoder from.
pub fn new(seed: [u8; 32]) -> Self {
Self {
encoder: ChaChaEncoder::new(seed),
}
}

/// Encodes a byte at the given position and direction in the transcript.
fn encode_byte(&self, dir: Direction, pos: usize) -> Vec<[Encoding; 2]> {
let id = match dir {
Direction::Sent => TX_TRANSCRIPT_ID,
Direction::Received => RX_TRANSCRIPT_ID,
};

let id_hash = blake3(format!("{}/{}", id, pos).as_bytes());
let id = u64::from_be_bytes(id_hash[..8].try_into().unwrap());

let mut encodings = <ChaChaEncoder as mpz_garble_core::Encoder>::encode_by_type(
&self.encoder,
id,
&ValueType::U8,
)
.iter_blocks()
.map(|blocks| {
// Hash the encodings to break the correlation and truncate them.
[
Encoding::new(
blake3(&Block::to_bytes(blocks[0]))[0..SSP / 8]
.try_into()
.unwrap(),
false,
),
Encoding::new(
blake3(&Block::to_bytes(blocks[1]))[0..SSP / 8]
.try_into()
.unwrap(),
true,
),
]
})
.collect::<Vec<_>>();
// Reverse byte encodings to MSB0.
encodings.reverse();
encodings
}
}

impl EncodingProvider<SingleRange> for TranscriptEncoder {
fn get_by_ids(
&self,
ids: &SingleRange,
) -> Result<FullEncodings<SingleRange>, EncodingProviderError> {
let mut full_encoding = Vec::with_capacity(ids.range().len() * 8);

for pos in ids.range().clone() {
full_encoding.extend(self.encode_byte(*ids.direction(), pos));
}

Ok(FullEncodings::new(full_encoding, ids.clone()))
}
}
6 changes: 6 additions & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ edition = "2021"
[features]
default = []
fixtures = ["dep:hex", "dep:tlsn-data-fixtures"]
# Enables support for Poseidon hashes as specified in the `poseidon-halo2` crate.
# This feature can only be used if the prover and the verifier enable the `authdecode_unsafe` feature.
# This feature is EXPERIMENTAL and will be removed in future releases without prior notice.
use_poseidon_halo2 = ["poseidon-halo2"]

[dependencies]
tlsn-data-fixtures = { workspace = true, optional = true }
tlsn-tls-core = { workspace = true, features = ["serde"] }
tlsn-utils = { workspace = true }
tlsn-utils-aio = { workspace = true }

mpz-core = { workspace = true }
mpz-garble-core = { workspace = true }
Expand All @@ -29,6 +34,7 @@ hex = { workspace = true, optional = true }
k256 = { workspace = true }
opaque-debug = { workspace = true }
p256 = { workspace = true, features = ["serde"] }
poseidon-halo2 = { workspace = true, optional = true }
rand = { workspace = true }
rand_core = { workspace = true }
rs_merkle = { workspace = true, features = ["serde"] }
Expand Down
Loading

0 comments on commit e90159f

Please sign in to comment.