fix(tlsn): do not implicitly reveal encoder secret (#1011)

This commit is contained in:
sinu.eth
2025-10-10 08:39:24 -07:00
committed by GitHub
parent 6b9f44e7e5
commit f99fce5b5a
13 changed files with 162 additions and 111 deletions

View File

@@ -5,7 +5,7 @@ use rand::{Rng, rng};
use tlsn_core::{ use tlsn_core::{
connection::{ConnectionInfo, ServerEphemKey}, connection::{ConnectionInfo, ServerEphemKey},
hash::HashAlgId, hash::HashAlgId,
transcript::TranscriptCommitment, transcript::{TranscriptCommitment, encoding::EncoderSecret},
}; };
use crate::{ use crate::{
@@ -25,6 +25,7 @@ pub struct Sign {
connection_info: Option<ConnectionInfo>, connection_info: Option<ConnectionInfo>,
server_ephemeral_key: Option<ServerEphemKey>, server_ephemeral_key: Option<ServerEphemKey>,
cert_commitment: ServerCertCommitment, cert_commitment: ServerCertCommitment,
encoder_secret: Option<EncoderSecret>,
extensions: Vec<Extension>, extensions: Vec<Extension>,
transcript_commitments: Vec<TranscriptCommitment>, transcript_commitments: Vec<TranscriptCommitment>,
} }
@@ -86,6 +87,7 @@ impl<'a> AttestationBuilder<'a, Accept> {
connection_info: None, connection_info: None,
server_ephemeral_key: None, server_ephemeral_key: None,
cert_commitment, cert_commitment,
encoder_secret: None,
transcript_commitments: Vec::new(), transcript_commitments: Vec::new(),
extensions, extensions,
}, },
@@ -106,6 +108,12 @@ impl AttestationBuilder<'_, Sign> {
self self
} }
/// Sets the secret for encoding commitments.
pub fn encoder_secret(&mut self, secret: EncoderSecret) -> &mut Self {
self.state.encoder_secret = Some(secret);
self
}
/// Adds an extension to the attestation. /// Adds an extension to the attestation.
pub fn extension(&mut self, extension: Extension) -> &mut Self { pub fn extension(&mut self, extension: Extension) -> &mut Self {
self.state.extensions.push(extension); self.state.extensions.push(extension);
@@ -129,6 +137,7 @@ impl AttestationBuilder<'_, Sign> {
connection_info, connection_info,
server_ephemeral_key, server_ephemeral_key,
cert_commitment, cert_commitment,
encoder_secret,
extensions, extensions,
transcript_commitments, transcript_commitments,
} = self.state; } = self.state;
@@ -159,6 +168,7 @@ impl AttestationBuilder<'_, Sign> {
AttestationBuilderError::new(ErrorKind::Field, "handshake data was not set") AttestationBuilderError::new(ErrorKind::Field, "handshake data was not set")
})?), })?),
cert_commitment: field_id.next(cert_commitment), cert_commitment: field_id.next(cert_commitment),
encoder_secret: encoder_secret.map(|secret| field_id.next(secret)),
extensions: extensions extensions: extensions
.into_iter() .into_iter()
.map(|extension| field_id.next(extension)) .map(|extension| field_id.next(extension))

View File

@@ -219,7 +219,7 @@ use tlsn_core::{
connection::{ConnectionInfo, ServerEphemKey}, connection::{ConnectionInfo, ServerEphemKey},
hash::{Hash, HashAlgorithm, TypedHash}, hash::{Hash, HashAlgorithm, TypedHash},
merkle::MerkleTree, merkle::MerkleTree,
transcript::TranscriptCommitment, transcript::{TranscriptCommitment, encoding::EncoderSecret},
}; };
use crate::{ use crate::{
@@ -327,6 +327,7 @@ pub struct Body {
connection_info: Field<ConnectionInfo>, connection_info: Field<ConnectionInfo>,
server_ephemeral_key: Field<ServerEphemKey>, server_ephemeral_key: Field<ServerEphemKey>,
cert_commitment: Field<ServerCertCommitment>, cert_commitment: Field<ServerCertCommitment>,
encoder_secret: Option<Field<EncoderSecret>>,
extensions: Vec<Field<Extension>>, extensions: Vec<Field<Extension>>,
transcript_commitments: Vec<Field<TranscriptCommitment>>, transcript_commitments: Vec<Field<TranscriptCommitment>>,
} }
@@ -372,6 +373,7 @@ impl Body {
connection_info: conn_info, connection_info: conn_info,
server_ephemeral_key, server_ephemeral_key,
cert_commitment, cert_commitment,
encoder_secret,
extensions, extensions,
transcript_commitments, transcript_commitments,
} = self; } = self;
@@ -389,6 +391,13 @@ impl Body {
), ),
]; ];
if let Some(encoder_secret) = encoder_secret {
fields.push((
encoder_secret.id,
hasher.hash_separated(&encoder_secret.data),
));
}
for field in extensions.iter() { for field in extensions.iter() {
fields.push((field.id, hasher.hash_separated(&field.data))); fields.push((field.id, hasher.hash_separated(&field.data)));
} }

View File

@@ -91,6 +91,11 @@ impl Presentation {
transcript.verify_with_provider( transcript.verify_with_provider(
&provider.hash, &provider.hash,
&attestation.body.connection_info().transcript_length, &attestation.body.connection_info().transcript_length,
attestation
.body
.encoder_secret
.as_ref()
.map(|field| &field.data),
attestation.body.transcript_commitments(), attestation.body.transcript_commitments(),
) )
}) })

View File

@@ -49,5 +49,6 @@ impl_domain_separator!(tlsn_core::connection::ConnectionInfo);
impl_domain_separator!(tlsn_core::connection::CertBinding); impl_domain_separator!(tlsn_core::connection::CertBinding);
impl_domain_separator!(tlsn_core::transcript::TranscriptCommitment); impl_domain_separator!(tlsn_core::transcript::TranscriptCommitment);
impl_domain_separator!(tlsn_core::transcript::TranscriptSecret); impl_domain_separator!(tlsn_core::transcript::TranscriptSecret);
impl_domain_separator!(tlsn_core::transcript::encoding::EncoderSecret);
impl_domain_separator!(tlsn_core::transcript::encoding::EncodingCommitment); impl_domain_separator!(tlsn_core::transcript::encoding::EncodingCommitment);
impl_domain_separator!(tlsn_core::transcript::hash::PlaintextHash); impl_domain_separator!(tlsn_core::transcript::hash::PlaintextHash);

View File

@@ -64,7 +64,6 @@ fn test_api() {
let encoding_commitment = EncodingCommitment { let encoding_commitment = EncodingCommitment {
root: encoding_tree.root(), root: encoding_tree.root(),
secret: encoder_secret(),
}; };
let request_config = RequestConfig::default(); let request_config = RequestConfig::default();
@@ -96,6 +95,7 @@ fn test_api() {
.connection_info(connection_info.clone()) .connection_info(connection_info.clone())
// Server key Notary received during handshake // Server key Notary received during handshake
.server_ephemeral_key(server_ephemeral_key) .server_ephemeral_key(server_ephemeral_key)
.encoder_secret(encoder_secret())
.transcript_commitments(vec![TranscriptCommitment::Encoding(encoding_commitment)]); .transcript_commitments(vec![TranscriptCommitment::Encoding(encoding_commitment)]);
let attestation = attestation_builder.build(&provider).unwrap(); let attestation = attestation_builder.build(&provider).unwrap();

View File

@@ -20,8 +20,8 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
connection::{HandshakeData, ServerName}, connection::{HandshakeData, ServerName},
transcript::{ transcript::{
Direction, PartialTranscript, Transcript, TranscriptCommitConfig, TranscriptCommitRequest, encoding::EncoderSecret, Direction, PartialTranscript, Transcript, TranscriptCommitConfig,
TranscriptCommitment, TranscriptSecret, TranscriptCommitRequest, TranscriptCommitment, TranscriptSecret,
}, },
}; };
@@ -220,6 +220,8 @@ pub struct VerifierOutput {
pub server_name: Option<ServerName>, pub server_name: Option<ServerName>,
/// Transcript data. /// Transcript data.
pub transcript: Option<PartialTranscript>, pub transcript: Option<PartialTranscript>,
/// Encoding commitment secret.
pub encoder_secret: Option<EncoderSecret>,
/// Transcript commitments. /// Transcript commitments.
pub transcript_commitments: Vec<TranscriptCommitment>, pub transcript_commitments: Vec<TranscriptCommitment>,
} }

View File

@@ -19,6 +19,4 @@ use crate::hash::TypedHash;
pub struct EncodingCommitment { pub struct EncodingCommitment {
/// Merkle root of the encoding commitments. /// Merkle root of the encoding commitments.
pub root: TypedHash, pub root: TypedHash,
/// Seed used to generate the encodings.
pub secret: EncoderSecret,
} }

View File

@@ -8,7 +8,7 @@ use crate::{
merkle::{MerkleError, MerkleProof}, merkle::{MerkleError, MerkleProof},
transcript::{ transcript::{
commit::MAX_TOTAL_COMMITTED_DATA, commit::MAX_TOTAL_COMMITTED_DATA,
encoding::{new_encoder, Encoder, EncodingCommitment}, encoding::{new_encoder, Encoder, EncoderSecret, EncodingCommitment},
Direction, Direction,
}, },
}; };
@@ -48,13 +48,14 @@ impl EncodingProof {
pub fn verify_with_provider( pub fn verify_with_provider(
&self, &self,
provider: &HashProvider, provider: &HashProvider,
secret: &EncoderSecret,
commitment: &EncodingCommitment, commitment: &EncodingCommitment,
sent: &[u8], sent: &[u8],
recv: &[u8], recv: &[u8],
) -> Result<(RangeSet<usize>, RangeSet<usize>), EncodingProofError> { ) -> Result<(RangeSet<usize>, RangeSet<usize>), EncodingProofError> {
let hasher = provider.get(&commitment.root.alg)?; let hasher = provider.get(&commitment.root.alg)?;
let encoder = new_encoder(&commitment.secret); let encoder = new_encoder(secret);
let Self { let Self {
inclusion_proof, inclusion_proof,
openings, openings,
@@ -232,10 +233,7 @@ mod test {
use crate::{ use crate::{
fixtures::{encoder_secret, encoder_secret_tampered_seed, encoding_provider}, fixtures::{encoder_secret, encoder_secret_tampered_seed, encoding_provider},
hash::Blake3, hash::Blake3,
transcript::{ transcript::{encoding::EncodingTree, Transcript},
encoding::{EncoderSecret, EncodingTree},
Transcript,
},
}; };
use super::*; use super::*;
@@ -246,7 +244,7 @@ mod test {
commitment: EncodingCommitment, commitment: EncodingCommitment,
} }
fn new_encoding_fixture(secret: EncoderSecret) -> EncodingFixture { fn new_encoding_fixture() -> EncodingFixture {
let transcript = Transcript::new(POST_JSON, OK_JSON); let transcript = Transcript::new(POST_JSON, OK_JSON);
let idx_0 = (Direction::Sent, RangeSet::from(0..POST_JSON.len())); let idx_0 = (Direction::Sent, RangeSet::from(0..POST_JSON.len()));
@@ -257,10 +255,7 @@ mod test {
let proof = tree.proof([&idx_0, &idx_1].into_iter()).unwrap(); let proof = tree.proof([&idx_0, &idx_1].into_iter()).unwrap();
let commitment = EncodingCommitment { let commitment = EncodingCommitment { root: tree.root() };
root: tree.root(),
secret,
};
EncodingFixture { EncodingFixture {
transcript, transcript,
@@ -275,11 +270,12 @@ mod test {
transcript, transcript,
proof, proof,
commitment, commitment,
} = new_encoding_fixture(encoder_secret_tampered_seed()); } = new_encoding_fixture();
let err = proof let err = proof
.verify_with_provider( .verify_with_provider(
&HashProvider::default(), &HashProvider::default(),
&encoder_secret_tampered_seed(),
&commitment, &commitment,
transcript.sent(), transcript.sent(),
transcript.received(), transcript.received(),
@@ -295,13 +291,19 @@ mod test {
transcript, transcript,
proof, proof,
commitment, commitment,
} = new_encoding_fixture(encoder_secret()); } = new_encoding_fixture();
let sent = &transcript.sent()[transcript.sent().len() - 1..]; let sent = &transcript.sent()[transcript.sent().len() - 1..];
let recv = &transcript.received()[transcript.received().len() - 2..]; let recv = &transcript.received()[transcript.received().len() - 2..];
let err = proof let err = proof
.verify_with_provider(&HashProvider::default(), &commitment, sent, recv) .verify_with_provider(
&HashProvider::default(),
&encoder_secret(),
&commitment,
sent,
recv,
)
.unwrap_err(); .unwrap_err();
assert!(matches!(err.kind, ErrorKind::Proof)); assert!(matches!(err.kind, ErrorKind::Proof));
@@ -313,7 +315,7 @@ mod test {
transcript, transcript,
mut proof, mut proof,
commitment, commitment,
} = new_encoding_fixture(encoder_secret()); } = new_encoding_fixture();
let Opening { idx, .. } = proof.openings.values_mut().next().unwrap(); let Opening { idx, .. } = proof.openings.values_mut().next().unwrap();
@@ -322,6 +324,7 @@ mod test {
let err = proof let err = proof
.verify_with_provider( .verify_with_provider(
&HashProvider::default(), &HashProvider::default(),
&encoder_secret(),
&commitment, &commitment,
transcript.sent(), transcript.sent(),
transcript.received(), transcript.received(),
@@ -337,7 +340,7 @@ mod test {
transcript, transcript,
mut proof, mut proof,
commitment, commitment,
} = new_encoding_fixture(encoder_secret()); } = new_encoding_fixture();
let Opening { blinder, .. } = proof.openings.values_mut().next().unwrap(); let Opening { blinder, .. } = proof.openings.values_mut().next().unwrap();
@@ -346,6 +349,7 @@ mod test {
let err = proof let err = proof
.verify_with_provider( .verify_with_provider(
&HashProvider::default(), &HashProvider::default(),
&encoder_secret(),
&commitment, &commitment,
transcript.sent(), transcript.sent(),
transcript.received(), transcript.received(),

View File

@@ -222,14 +222,12 @@ mod tests {
let proof = tree.proof([&idx_0, &idx_1].into_iter()).unwrap(); let proof = tree.proof([&idx_0, &idx_1].into_iter()).unwrap();
let commitment = EncodingCommitment { let commitment = EncodingCommitment { root: tree.root() };
root: tree.root(),
secret: encoder_secret(),
};
let (auth_sent, auth_recv) = proof let (auth_sent, auth_recv) = proof
.verify_with_provider( .verify_with_provider(
&HashProvider::default(), &HashProvider::default(),
&encoder_secret(),
&commitment, &commitment,
transcript.sent(), transcript.sent(),
transcript.received(), transcript.received(),
@@ -260,14 +258,12 @@ mod tests {
.proof([&idx_0, &idx_1, &idx_2, &idx_3].into_iter()) .proof([&idx_0, &idx_1, &idx_2, &idx_3].into_iter())
.unwrap(); .unwrap();
let commitment = EncodingCommitment { let commitment = EncodingCommitment { root: tree.root() };
root: tree.root(),
secret: encoder_secret(),
};
let (auth_sent, auth_recv) = proof let (auth_sent, auth_recv) = proof
.verify_with_provider( .verify_with_provider(
&HashProvider::default(), &HashProvider::default(),
&encoder_secret(),
&commitment, &commitment,
transcript.sent(), transcript.sent(),
transcript.received(), transcript.received(),

View File

@@ -10,7 +10,7 @@ use crate::{
hash::{HashAlgId, HashProvider}, hash::{HashAlgId, HashProvider},
transcript::{ transcript::{
commit::{TranscriptCommitment, TranscriptCommitmentKind}, commit::{TranscriptCommitment, TranscriptCommitmentKind},
encoding::{EncodingProof, EncodingProofError, EncodingTree}, encoding::{EncoderSecret, EncodingProof, EncodingProofError, EncodingTree},
hash::{hash_plaintext, PlaintextHash, PlaintextHashSecret}, hash::{hash_plaintext, PlaintextHash, PlaintextHashSecret},
Direction, PartialTranscript, RangeSet, Transcript, TranscriptSecret, Direction, PartialTranscript, RangeSet, Transcript, TranscriptSecret,
}, },
@@ -51,6 +51,7 @@ impl TranscriptProof {
self, self,
provider: &HashProvider, provider: &HashProvider,
length: &TranscriptLength, length: &TranscriptLength,
encoder_secret: Option<&EncoderSecret>,
commitments: impl IntoIterator<Item = &'a TranscriptCommitment>, commitments: impl IntoIterator<Item = &'a TranscriptCommitment>,
) -> Result<PartialTranscript, TranscriptProofError> { ) -> Result<PartialTranscript, TranscriptProofError> {
let mut encoding_commitment = None; let mut encoding_commitment = None;
@@ -86,6 +87,13 @@ impl TranscriptProof {
// Verify encoding proof. // Verify encoding proof.
if let Some(proof) = self.encoding_proof { if let Some(proof) = self.encoding_proof {
let secret = encoder_secret.ok_or_else(|| {
TranscriptProofError::new(
ErrorKind::Encoding,
"contains an encoding proof but missing encoder secret",
)
})?;
let commitment = encoding_commitment.ok_or_else(|| { let commitment = encoding_commitment.ok_or_else(|| {
TranscriptProofError::new( TranscriptProofError::new(
ErrorKind::Encoding, ErrorKind::Encoding,
@@ -95,6 +103,7 @@ impl TranscriptProof {
let (auth_sent, auth_recv) = proof.verify_with_provider( let (auth_sent, auth_recv) = proof.verify_with_provider(
provider, provider,
secret,
commitment, commitment,
self.transcript.sent_unsafe(), self.transcript.sent_unsafe(),
self.transcript.received_unsafe(), self.transcript.received_unsafe(),
@@ -575,7 +584,7 @@ mod tests {
use tlsn_data_fixtures::http::{request::GET_WITH_HEADER, response::OK_JSON}; use tlsn_data_fixtures::http::{request::GET_WITH_HEADER, response::OK_JSON};
use crate::{ use crate::{
fixtures::encoding_provider, fixtures::{encoder_secret, encoding_provider},
hash::{Blake3, Blinder, HashAlgId}, hash::{Blake3, Blinder, HashAlgId},
transcript::TranscriptCommitConfigBuilder, transcript::TranscriptCommitConfigBuilder,
}; };
@@ -602,7 +611,12 @@ mod tests {
let provider = HashProvider::default(); let provider = HashProvider::default();
let err = transcript_proof let err = transcript_proof
.verify_with_provider(&provider, &transcript.length(), &[]) .verify_with_provider(
&provider,
&transcript.length(),
Some(&encoder_secret()),
&[],
)
.err() .err()
.unwrap(); .unwrap();
@@ -676,6 +690,7 @@ mod tests {
.verify_with_provider( .verify_with_provider(
&provider, &provider,
&transcript.length(), &transcript.length(),
None,
&[TranscriptCommitment::Hash(commitment)], &[TranscriptCommitment::Hash(commitment)],
) )
.unwrap(); .unwrap();
@@ -724,6 +739,7 @@ mod tests {
.verify_with_provider( .verify_with_provider(
&provider, &provider,
&transcript.length(), &transcript.length(),
None,
&[TranscriptCommitment::Hash(commitment)], &[TranscriptCommitment::Hash(commitment)],
) )
.unwrap_err(); .unwrap_err();

View File

@@ -43,7 +43,7 @@ pub(crate) async fn transfer<K: KeyStore>(
store: &K, store: &K,
sent: &ReferenceMap, sent: &ReferenceMap,
recv: &ReferenceMap, recv: &ReferenceMap,
) -> Result<EncodingCommitment, EncodingError> { ) -> Result<(EncoderSecret, EncodingCommitment), EncodingError> {
let secret = EncoderSecret::new(rand::rng().random(), store.delta().as_block().to_bytes()); let secret = EncoderSecret::new(rand::rng().random(), store.delta().as_block().to_bytes());
let encoder = new_encoder(&secret); let encoder = new_encoder(&secret);
@@ -83,9 +83,8 @@ pub(crate) async fn transfer<K: KeyStore>(
ctx.io_mut().with_limit(frame_limit).send(encodings).await?; ctx.io_mut().with_limit(frame_limit).send(encodings).await?;
let root = ctx.io_mut().expect_next().await?; let root = ctx.io_mut().expect_next().await?;
ctx.io_mut().send(secret.clone()).await?;
Ok(EncodingCommitment { root, secret }) Ok((secret, EncodingCommitment { root }))
} }
/// Receives and commits to the encodings for the provided plaintext ranges. /// Receives and commits to the encodings for the provided plaintext ranges.
@@ -166,9 +165,8 @@ pub(crate) async fn receive<M: MacStore>(
let root = tree.root(); let root = tree.root();
ctx.io_mut().send(root.clone()).await?; ctx.io_mut().send(root.clone()).await?;
let secret = ctx.io_mut().expect_next().await?;
let commitment = EncodingCommitment { root, secret }; let commitment = EncodingCommitment { root };
Ok((commitment, tree)) Ok((commitment, tree))
} }

View File

@@ -135,6 +135,7 @@ pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
sent_proof.verify().map_err(VerifierError::verify)?; sent_proof.verify().map_err(VerifierError::verify)?;
recv_proof.verify().map_err(VerifierError::verify)?; recv_proof.verify().map_err(VerifierError::verify)?;
let mut encoder_secret = None;
if let Some(commit_config) = transcript_commit if let Some(commit_config) = transcript_commit
&& let Some((sent, recv)) = commit_config.encoding() && let Some((sent, recv)) = commit_config.encoding()
{ {
@@ -147,7 +148,8 @@ pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
.index(recv) .index(recv)
.expect("ranges were authenticated"); .expect("ranges were authenticated");
let commitment = encoding::transfer(ctx, vm, &sent_map, &recv_map).await?; let (secret, commitment) = encoding::transfer(ctx, vm, &sent_map, &recv_map).await?;
encoder_secret = Some(secret);
transcript_commitments.push(TranscriptCommitment::Encoding(commitment)); transcript_commitments.push(TranscriptCommitment::Encoding(commitment));
} }
@@ -160,6 +162,7 @@ pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
Ok(VerifierOutput { Ok(VerifierOutput {
server_name, server_name,
transcript: has_reveal.then_some(transcript), transcript: has_reveal.then_some(transcript),
encoder_secret,
transcript_commitments, transcript_commitments,
}) })
} }

View File

@@ -6,11 +6,12 @@ use tlsn::{
hash::{HashAlgId, HashProvider}, hash::{HashAlgId, HashProvider},
prover::{ProveConfig, Prover, ProverConfig, TlsConfig}, prover::{ProveConfig, Prover, ProverConfig, TlsConfig},
transcript::{ transcript::{
Direction, TranscriptCommitConfig, TranscriptCommitment, TranscriptCommitmentKind, Direction, Transcript, TranscriptCommitConfig, TranscriptCommitment,
TranscriptSecret, TranscriptCommitmentKind, TranscriptSecret,
}, },
verifier::{Verifier, VerifierConfig, VerifierOutput, VerifyConfig}, verifier::{Verifier, VerifierConfig, VerifierOutput, VerifyConfig},
}; };
use tlsn_core::ProverOutput;
use tlsn_server_fixture::bind; use tlsn_server_fixture::bind;
use tlsn_server_fixture_certs::{CA_CERT_DER, SERVER_DOMAIN}; use tlsn_server_fixture_certs::{CA_CERT_DER, SERVER_DOMAIN};
@@ -34,11 +35,80 @@ async fn test() {
let (socket_0, socket_1) = tokio::io::duplex(2 << 23); let (socket_0, socket_1) = tokio::io::duplex(2 << 23);
tokio::join!(prover(socket_0), verifier(socket_1)); let ((full_transcript, prover_output), verifier_output) =
tokio::join!(prover(socket_0), verifier(socket_1));
let partial_transcript = verifier_output.transcript.unwrap();
let ServerName::Dns(server_name) = verifier_output.server_name.unwrap();
assert_eq!(server_name.as_str(), SERVER_DOMAIN);
assert!(!partial_transcript.is_complete());
assert_eq!(
partial_transcript
.sent_authed()
.iter_ranges()
.next()
.unwrap(),
0..10
);
assert_eq!(
partial_transcript
.received_authed()
.iter_ranges()
.next()
.unwrap(),
0..10
);
let encoding_tree = prover_output
.transcript_secrets
.iter()
.find_map(|secret| {
if let TranscriptSecret::Encoding(tree) = secret {
Some(tree)
} else {
None
}
})
.unwrap();
let encoding_commitment = prover_output
.transcript_commitments
.iter()
.find_map(|commitment| {
if let TranscriptCommitment::Encoding(commitment) = commitment {
Some(commitment)
} else {
None
}
})
.unwrap();
let prove_sent = RangeSet::from(1..full_transcript.sent().len() - 1);
let prove_recv = RangeSet::from(1..full_transcript.received().len() - 1);
let idxs = [
(Direction::Sent, prove_sent.clone()),
(Direction::Received, prove_recv.clone()),
];
let proof = encoding_tree.proof(idxs.iter()).unwrap();
let (auth_sent, auth_recv) = proof
.verify_with_provider(
&HashProvider::default(),
&verifier_output.encoder_secret.unwrap(),
encoding_commitment,
full_transcript.sent(),
full_transcript.received(),
)
.unwrap();
assert_eq!(auth_sent, prove_sent);
assert_eq!(auth_recv, prove_recv);
} }
#[instrument(skip(verifier_socket))] #[instrument(skip(verifier_socket))]
async fn prover<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(verifier_socket: T) { async fn prover<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
verifier_socket: T,
) -> (Transcript, ProverOutput) {
let (client_socket, server_socket) = tokio::io::duplex(2 << 16); let (client_socket, server_socket) = tokio::io::duplex(2 << 16);
let server_task = tokio::spawn(bind(server_socket.compat())); let server_task = tokio::spawn(bind(server_socket.compat()));
@@ -127,52 +197,13 @@ async fn prover<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(verifier_soc
let output = prover.prove(&config).await.unwrap(); let output = prover.prove(&config).await.unwrap();
prover.close().await.unwrap(); prover.close().await.unwrap();
let encoding_tree = output (transcript, output)
.transcript_secrets
.iter()
.find_map(|secret| {
if let TranscriptSecret::Encoding(tree) = secret {
Some(tree)
} else {
None
}
})
.unwrap();
let encoding_commitment = output
.transcript_commitments
.iter()
.find_map(|commitment| {
if let TranscriptCommitment::Encoding(commitment) = commitment {
Some(commitment)
} else {
None
}
})
.unwrap();
let prove_sent = RangeSet::from(1..sent_tx_len - 1);
let prove_recv = RangeSet::from(1..recv_tx_len - 1);
let idxs = [
(Direction::Sent, prove_sent.clone()),
(Direction::Received, prove_recv.clone()),
];
let proof = encoding_tree.proof(idxs.iter()).unwrap();
let (auth_sent, auth_recv) = proof
.verify_with_provider(
&HashProvider::default(),
encoding_commitment,
transcript.sent(),
transcript.received(),
)
.unwrap();
assert_eq!(auth_sent, prove_sent);
assert_eq!(auth_recv, prove_recv);
} }
#[instrument(skip(socket))] #[instrument(skip(socket))]
async fn verifier<T: AsyncWrite + AsyncRead + Send + Sync + Unpin + 'static>(socket: T) { async fn verifier<T: AsyncWrite + AsyncRead + Send + Sync + Unpin + 'static>(
socket: T,
) -> VerifierOutput {
let config_validator = ProtocolConfigValidator::builder() let config_validator = ProtocolConfigValidator::builder()
.max_sent_data(MAX_SENT_DATA) .max_sent_data(MAX_SENT_DATA)
.max_recv_data(MAX_RECV_DATA) .max_recv_data(MAX_RECV_DATA)
@@ -197,30 +228,8 @@ async fn verifier<T: AsyncWrite + AsyncRead + Send + Sync + Unpin + 'static>(soc
.await .await
.unwrap(); .unwrap();
let VerifierOutput { let output = verifier.verify(&VerifyConfig::default()).await.unwrap();
server_name,
transcript,
transcript_commitments,
} = verifier.verify(&VerifyConfig::default()).await.unwrap();
verifier.close().await.unwrap(); verifier.close().await.unwrap();
let transcript = transcript.unwrap(); output
let ServerName::Dns(server_name) = server_name.unwrap();
assert_eq!(server_name.as_str(), SERVER_DOMAIN);
assert!(!transcript.is_complete());
assert_eq!(
transcript.sent_authed().iter_ranges().next().unwrap(),
0..10
);
assert_eq!(
transcript.received_authed().iter_ranges().next().unwrap(),
0..10
);
assert!(matches!(
transcript_commitments[0],
TranscriptCommitment::Encoding(_)
));
} }