mirror of
https://github.com/tlsnotary/tlsn.git
synced 2026-01-09 14:48:13 -05:00
chore: add core transcript unit tests (#649)
* Add transcript proof and lib tests. * Init encoding tree test. * Add encoding proof tests. * Generalise fixture tests. * Add seed arg to attestation fixture fn. * Adjust cosmetics. * Format comment. --------- Co-authored-by: yuroitaki <>
This commit is contained in:
@@ -245,64 +245,18 @@ mod test {
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
connection::{HandshakeData, HandshakeDataV1_2},
|
connection::{HandshakeData, HandshakeDataV1_2},
|
||||||
fixtures::{encoder_seed, encoding_provider, ConnectionFixture},
|
fixtures::{
|
||||||
|
encoder_seed, encoding_provider, request_fixture, ConnectionFixture, RequestFixture,
|
||||||
|
},
|
||||||
hash::Blake3,
|
hash::Blake3,
|
||||||
request::RequestConfig,
|
transcript::Transcript,
|
||||||
transcript::{encoding::EncodingTree, Transcript, TranscriptCommitConfigBuilder},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn request_and_connection() -> (Request, ConnectionFixture) {
|
|
||||||
let provider = CryptoProvider::default();
|
|
||||||
|
|
||||||
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
|
||||||
let (sent_len, recv_len) = transcript.len();
|
|
||||||
// Plaintext encodings which the Prover obtained from GC evaluation
|
|
||||||
let encodings_provider = encoding_provider(GET_WITH_HEADER, OK_JSON);
|
|
||||||
|
|
||||||
// At the end of the TLS connection the Prover holds the:
|
|
||||||
let ConnectionFixture {
|
|
||||||
server_name,
|
|
||||||
server_cert_data,
|
|
||||||
..
|
|
||||||
} = ConnectionFixture::tlsnotary(transcript.length());
|
|
||||||
|
|
||||||
// Prover specifies the ranges it wants to commit to.
|
|
||||||
let mut transcript_commitment_builder = TranscriptCommitConfigBuilder::new(&transcript);
|
|
||||||
transcript_commitment_builder
|
|
||||||
.commit_sent(&(0..sent_len))
|
|
||||||
.unwrap()
|
|
||||||
.commit_recv(&(0..recv_len))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let transcripts_commitment_config = transcript_commitment_builder.build().unwrap();
|
|
||||||
|
|
||||||
// Prover constructs encoding tree.
|
|
||||||
let encoding_tree = EncodingTree::new(
|
|
||||||
&Blake3::default(),
|
|
||||||
transcripts_commitment_config.iter_encoding(),
|
|
||||||
&encodings_provider,
|
|
||||||
&transcript.length(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let request_config = RequestConfig::default();
|
|
||||||
let mut request_builder = Request::builder(&request_config);
|
|
||||||
|
|
||||||
request_builder
|
|
||||||
.server_name(server_name.clone())
|
|
||||||
.server_cert_data(server_cert_data)
|
|
||||||
.transcript(transcript.clone())
|
|
||||||
.encoding_tree(encoding_tree);
|
|
||||||
let (request, _) = request_builder.build(&provider).unwrap();
|
|
||||||
|
|
||||||
(request, ConnectionFixture::tlsnotary(transcript.length()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[fixture]
|
#[fixture]
|
||||||
#[once]
|
#[once]
|
||||||
fn default_attestation_config() -> AttestationConfig {
|
fn attestation_config() -> AttestationConfig {
|
||||||
AttestationConfig::builder()
|
AttestationConfig::builder()
|
||||||
.supported_signature_algs([SignatureAlgId::SECP256K1])
|
.supported_signature_algs([SignatureAlgId::SECP256K1])
|
||||||
.build()
|
.build()
|
||||||
@@ -319,7 +273,16 @@ mod test {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_attestation_builder_accept_unsupported_signer() {
|
fn test_attestation_builder_accept_unsupported_signer() {
|
||||||
let (request, _) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
|
let RequestFixture { request, .. } = request_fixture(
|
||||||
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection,
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let attestation_config = AttestationConfig::builder()
|
let attestation_config = AttestationConfig::builder()
|
||||||
.supported_signature_algs([SignatureAlgId::SECP256R1])
|
.supported_signature_algs([SignatureAlgId::SECP256R1])
|
||||||
.build()
|
.build()
|
||||||
@@ -334,7 +297,15 @@ mod test {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_attestation_builder_accept_unsupported_hasher() {
|
fn test_attestation_builder_accept_unsupported_hasher() {
|
||||||
let (request, _) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
|
let RequestFixture { request, .. } = request_fixture(
|
||||||
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection,
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let attestation_config = AttestationConfig::builder()
|
let attestation_config = AttestationConfig::builder()
|
||||||
.supported_signature_algs([SignatureAlgId::SECP256K1])
|
.supported_signature_algs([SignatureAlgId::SECP256K1])
|
||||||
@@ -351,7 +322,15 @@ mod test {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_attestation_builder_accept_unsupported_encoding_commitment() {
|
fn test_attestation_builder_accept_unsupported_encoding_commitment() {
|
||||||
let (request, _) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
|
let RequestFixture { request, .. } = request_fixture(
|
||||||
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection,
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let attestation_config = AttestationConfig::builder()
|
let attestation_config = AttestationConfig::builder()
|
||||||
.supported_signature_algs([SignatureAlgId::SECP256K1])
|
.supported_signature_algs([SignatureAlgId::SECP256K1])
|
||||||
@@ -371,13 +350,19 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_attestation_builder_sign_missing_signer(
|
fn test_attestation_builder_sign_missing_signer(attestation_config: &AttestationConfig) {
|
||||||
default_attestation_config: &AttestationConfig,
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
) {
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
let (request, _) = request_and_connection();
|
|
||||||
|
|
||||||
let attestation_builder = Attestation::builder(default_attestation_config)
|
let RequestFixture { request, .. } = request_fixture(
|
||||||
.accept_request(request.clone())
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection,
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let attestation_builder = Attestation::builder(attestation_config)
|
||||||
|
.accept_request(request)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut provider = CryptoProvider::default();
|
let mut provider = CryptoProvider::default();
|
||||||
@@ -389,13 +374,21 @@ mod test {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_attestation_builder_sign_missing_encoding_seed(
|
fn test_attestation_builder_sign_missing_encoding_seed(
|
||||||
default_attestation_config: &AttestationConfig,
|
attestation_config: &AttestationConfig,
|
||||||
crypto_provider: &CryptoProvider,
|
crypto_provider: &CryptoProvider,
|
||||||
) {
|
) {
|
||||||
let (request, connection) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
let mut attestation_builder = Attestation::builder(default_attestation_config)
|
let RequestFixture { request, .. } = request_fixture(
|
||||||
.accept_request(request.clone())
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut attestation_builder = Attestation::builder(attestation_config)
|
||||||
|
.accept_request(request)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let ConnectionFixture {
|
let ConnectionFixture {
|
||||||
@@ -407,10 +400,10 @@ mod test {
|
|||||||
let HandshakeData::V1_2(HandshakeDataV1_2 {
|
let HandshakeData::V1_2(HandshakeDataV1_2 {
|
||||||
server_ephemeral_key,
|
server_ephemeral_key,
|
||||||
..
|
..
|
||||||
}) = server_cert_data.handshake.clone();
|
}) = server_cert_data.handshake;
|
||||||
|
|
||||||
attestation_builder
|
attestation_builder
|
||||||
.connection_info(connection_info.clone())
|
.connection_info(connection_info)
|
||||||
.server_ephemeral_key(server_ephemeral_key);
|
.server_ephemeral_key(server_ephemeral_key);
|
||||||
|
|
||||||
let err = attestation_builder.build(crypto_provider).err().unwrap();
|
let err = attestation_builder.build(crypto_provider).err().unwrap();
|
||||||
@@ -419,13 +412,21 @@ mod test {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_attestation_builder_sign_missing_server_ephemeral_key(
|
fn test_attestation_builder_sign_missing_server_ephemeral_key(
|
||||||
default_attestation_config: &AttestationConfig,
|
attestation_config: &AttestationConfig,
|
||||||
crypto_provider: &CryptoProvider,
|
crypto_provider: &CryptoProvider,
|
||||||
) {
|
) {
|
||||||
let (request, connection) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
let mut attestation_builder = Attestation::builder(default_attestation_config)
|
let RequestFixture { request, .. } = request_fixture(
|
||||||
.accept_request(request.clone())
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut attestation_builder = Attestation::builder(attestation_config)
|
||||||
|
.accept_request(request)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let ConnectionFixture {
|
let ConnectionFixture {
|
||||||
@@ -433,7 +434,7 @@ mod test {
|
|||||||
} = connection;
|
} = connection;
|
||||||
|
|
||||||
attestation_builder
|
attestation_builder
|
||||||
.connection_info(connection_info.clone())
|
.connection_info(connection_info)
|
||||||
.encoding_seed(encoder_seed().to_vec());
|
.encoding_seed(encoder_seed().to_vec());
|
||||||
|
|
||||||
let err = attestation_builder.build(crypto_provider).err().unwrap();
|
let err = attestation_builder.build(crypto_provider).err().unwrap();
|
||||||
@@ -442,13 +443,21 @@ mod test {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_attestation_builder_sign_missing_connection_info(
|
fn test_attestation_builder_sign_missing_connection_info(
|
||||||
default_attestation_config: &AttestationConfig,
|
attestation_config: &AttestationConfig,
|
||||||
crypto_provider: &CryptoProvider,
|
crypto_provider: &CryptoProvider,
|
||||||
) {
|
) {
|
||||||
let (request, connection) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
let mut attestation_builder = Attestation::builder(default_attestation_config)
|
let RequestFixture { request, .. } = request_fixture(
|
||||||
.accept_request(request.clone())
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut attestation_builder = Attestation::builder(attestation_config)
|
||||||
|
.accept_request(request)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let ConnectionFixture {
|
let ConnectionFixture {
|
||||||
@@ -458,7 +467,7 @@ mod test {
|
|||||||
let HandshakeData::V1_2(HandshakeDataV1_2 {
|
let HandshakeData::V1_2(HandshakeDataV1_2 {
|
||||||
server_ephemeral_key,
|
server_ephemeral_key,
|
||||||
..
|
..
|
||||||
}) = server_cert_data.handshake.clone();
|
}) = server_cert_data.handshake;
|
||||||
|
|
||||||
attestation_builder
|
attestation_builder
|
||||||
.server_ephemeral_key(server_ephemeral_key)
|
.server_ephemeral_key(server_ephemeral_key)
|
||||||
|
|||||||
@@ -8,14 +8,23 @@ use hex::FromHex;
|
|||||||
use p256::ecdsa::SigningKey;
|
use p256::ecdsa::SigningKey;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
attestation::{Attestation, AttestationConfig},
|
||||||
connection::{
|
connection::{
|
||||||
Certificate, ConnectionInfo, HandshakeData, HandshakeDataV1_2, KeyType, ServerCertData,
|
Certificate, ConnectionInfo, HandshakeData, HandshakeDataV1_2, KeyType, ServerCertData,
|
||||||
ServerEphemKey, ServerName, ServerSignature, SignatureScheme, TlsVersion, TranscriptLength,
|
ServerEphemKey, ServerName, ServerSignature, SignatureScheme, TlsVersion, TranscriptLength,
|
||||||
},
|
},
|
||||||
transcript::{encoding::EncodingProvider, Transcript},
|
hash::HashAlgorithm,
|
||||||
|
request::{Request, RequestConfig},
|
||||||
|
signing::SignatureAlgId,
|
||||||
|
transcript::{
|
||||||
|
encoding::{EncodingProvider, EncodingTree},
|
||||||
|
Transcript, TranscriptCommitConfigBuilder,
|
||||||
|
},
|
||||||
|
CryptoProvider,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A fixture containing various TLS connection data.
|
/// A fixture containing various TLS connection data.
|
||||||
|
#[derive(Clone)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub struct ConnectionFixture {
|
pub struct ConnectionFixture {
|
||||||
pub server_name: ServerName,
|
pub server_name: ServerName,
|
||||||
@@ -134,3 +143,101 @@ pub fn encoder_seed() -> [u8; 32] {
|
|||||||
pub fn notary_signing_key() -> SigningKey {
|
pub fn notary_signing_key() -> SigningKey {
|
||||||
SigningKey::from_slice(&[1; 32]).unwrap()
|
SigningKey::from_slice(&[1; 32]).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A Request fixture used for testing.
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub struct RequestFixture {
|
||||||
|
pub encoding_tree: EncodingTree,
|
||||||
|
pub request: Request,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a request fixture for testing.
|
||||||
|
pub fn request_fixture(
|
||||||
|
transcript: Transcript,
|
||||||
|
encodings_provider: impl EncodingProvider,
|
||||||
|
connection: ConnectionFixture,
|
||||||
|
encoding_hasher: impl HashAlgorithm,
|
||||||
|
) -> RequestFixture {
|
||||||
|
let provider = CryptoProvider::default();
|
||||||
|
let (sent_len, recv_len) = transcript.len();
|
||||||
|
|
||||||
|
let ConnectionFixture {
|
||||||
|
server_name,
|
||||||
|
server_cert_data,
|
||||||
|
..
|
||||||
|
} = connection;
|
||||||
|
|
||||||
|
let mut transcript_commitment_builder = TranscriptCommitConfigBuilder::new(&transcript);
|
||||||
|
transcript_commitment_builder
|
||||||
|
.commit_sent(&(0..sent_len))
|
||||||
|
.unwrap()
|
||||||
|
.commit_recv(&(0..recv_len))
|
||||||
|
.unwrap();
|
||||||
|
let transcripts_commitment_config = transcript_commitment_builder.build().unwrap();
|
||||||
|
|
||||||
|
// Prover constructs encoding tree.
|
||||||
|
let encoding_tree = EncodingTree::new(
|
||||||
|
&encoding_hasher,
|
||||||
|
transcripts_commitment_config.iter_encoding(),
|
||||||
|
&encodings_provider,
|
||||||
|
&transcript.length(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let request_config = RequestConfig::default();
|
||||||
|
let mut request_builder = Request::builder(&request_config);
|
||||||
|
request_builder
|
||||||
|
.server_name(server_name)
|
||||||
|
.server_cert_data(server_cert_data)
|
||||||
|
.transcript(transcript)
|
||||||
|
.encoding_tree(encoding_tree.clone());
|
||||||
|
|
||||||
|
let (request, _) = request_builder.build(&provider).unwrap();
|
||||||
|
|
||||||
|
RequestFixture {
|
||||||
|
encoding_tree,
|
||||||
|
request,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an attestation fixture for testing.
|
||||||
|
pub fn attestation_fixture(
|
||||||
|
request: Request,
|
||||||
|
connection: ConnectionFixture,
|
||||||
|
signature_alg: SignatureAlgId,
|
||||||
|
encoding_seed: Vec<u8>,
|
||||||
|
) -> Attestation {
|
||||||
|
let ConnectionFixture {
|
||||||
|
connection_info,
|
||||||
|
server_cert_data,
|
||||||
|
..
|
||||||
|
} = connection;
|
||||||
|
|
||||||
|
let HandshakeData::V1_2(HandshakeDataV1_2 {
|
||||||
|
server_ephemeral_key,
|
||||||
|
..
|
||||||
|
}) = server_cert_data.handshake;
|
||||||
|
|
||||||
|
let mut provider = CryptoProvider::default();
|
||||||
|
match signature_alg {
|
||||||
|
SignatureAlgId::SECP256K1 => provider.signer.set_secp256k1(&[42u8; 32]).unwrap(),
|
||||||
|
SignatureAlgId::SECP256R1 => provider.signer.set_secp256r1(&[42u8; 32]).unwrap(),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let attestation_config = AttestationConfig::builder()
|
||||||
|
.supported_signature_algs([signature_alg])
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut attestation_builder = Attestation::builder(&attestation_config)
|
||||||
|
.accept_request(request)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
attestation_builder
|
||||||
|
.connection_info(connection_info)
|
||||||
|
.server_ephemeral_key(server_ephemeral_key)
|
||||||
|
.encoding_seed(encoding_seed);
|
||||||
|
|
||||||
|
attestation_builder.build(&provider).unwrap()
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,115 +90,62 @@ pub struct InconsistentAttestation(String);
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use tlsn_data_fixtures::http::{request::GET_WITH_HEADER, response::OK_JSON};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
attestation::{Attestation, AttestationConfig},
|
connection::{ServerCertOpening, TranscriptLength},
|
||||||
connection::{HandshakeData, HandshakeDataV1_2, ServerCertOpening, TranscriptLength},
|
fixtures::{
|
||||||
fixtures::{encoder_seed, encoding_provider, ConnectionFixture},
|
attestation_fixture, encoder_seed, encoding_provider, request_fixture,
|
||||||
|
ConnectionFixture, RequestFixture,
|
||||||
|
},
|
||||||
hash::{Blake3, Hash, HashAlgId},
|
hash::{Blake3, Hash, HashAlgId},
|
||||||
signing::SignatureAlgId,
|
signing::SignatureAlgId,
|
||||||
transcript::{encoding::EncodingTree, Transcript, TranscriptCommitConfigBuilder},
|
transcript::Transcript,
|
||||||
CryptoProvider,
|
CryptoProvider,
|
||||||
};
|
};
|
||||||
|
|
||||||
use tlsn_data_fixtures::http::{request::GET_WITH_HEADER, response::OK_JSON};
|
|
||||||
|
|
||||||
fn attestation(payload: (Request, ConnectionFixture)) -> Attestation {
|
|
||||||
let (request, connection) = payload;
|
|
||||||
|
|
||||||
let ConnectionFixture {
|
|
||||||
connection_info,
|
|
||||||
server_cert_data,
|
|
||||||
..
|
|
||||||
} = connection;
|
|
||||||
|
|
||||||
let HandshakeData::V1_2(HandshakeDataV1_2 {
|
|
||||||
server_ephemeral_key,
|
|
||||||
..
|
|
||||||
}) = server_cert_data.handshake.clone();
|
|
||||||
|
|
||||||
let mut provider = CryptoProvider::default();
|
|
||||||
provider.signer.set_secp256k1(&[42u8; 32]).unwrap();
|
|
||||||
|
|
||||||
let attestation_config = AttestationConfig::builder()
|
|
||||||
.supported_signature_algs([SignatureAlgId::SECP256K1])
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut attestation_builder = Attestation::builder(&attestation_config)
|
|
||||||
.accept_request(request.clone())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
attestation_builder
|
|
||||||
.connection_info(connection_info.clone())
|
|
||||||
.server_ephemeral_key(server_ephemeral_key)
|
|
||||||
.encoding_seed(encoder_seed().to_vec());
|
|
||||||
|
|
||||||
attestation_builder.build(&provider).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn request_and_connection() -> (Request, ConnectionFixture) {
|
|
||||||
let provider = CryptoProvider::default();
|
|
||||||
|
|
||||||
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
|
||||||
let (sent_len, recv_len) = transcript.len();
|
|
||||||
// Plaintext encodings which the Prover obtained from GC evaluation.
|
|
||||||
let encodings_provider = encoding_provider(GET_WITH_HEADER, OK_JSON);
|
|
||||||
|
|
||||||
// At the end of the TLS connection the Prover holds the:
|
|
||||||
let ConnectionFixture {
|
|
||||||
server_name,
|
|
||||||
server_cert_data,
|
|
||||||
..
|
|
||||||
} = ConnectionFixture::tlsnotary(transcript.length());
|
|
||||||
|
|
||||||
// Prover specifies the ranges it wants to commit to.
|
|
||||||
let mut transcript_commitment_builder = TranscriptCommitConfigBuilder::new(&transcript);
|
|
||||||
transcript_commitment_builder
|
|
||||||
.commit_sent(&(0..sent_len))
|
|
||||||
.unwrap()
|
|
||||||
.commit_recv(&(0..recv_len))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let transcripts_commitment_config = transcript_commitment_builder.build().unwrap();
|
|
||||||
|
|
||||||
// Prover constructs encoding tree.
|
|
||||||
let encoding_tree = EncodingTree::new(
|
|
||||||
&Blake3::default(),
|
|
||||||
transcripts_commitment_config.iter_encoding(),
|
|
||||||
&encodings_provider,
|
|
||||||
&transcript.length(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let request_config = RequestConfig::default();
|
|
||||||
let mut request_builder = Request::builder(&request_config);
|
|
||||||
|
|
||||||
request_builder
|
|
||||||
.server_name(server_name.clone())
|
|
||||||
.server_cert_data(server_cert_data)
|
|
||||||
.transcript(transcript.clone())
|
|
||||||
.encoding_tree(encoding_tree);
|
|
||||||
let (request, _) = request_builder.build(&provider).unwrap();
|
|
||||||
|
|
||||||
(request, ConnectionFixture::tlsnotary(transcript.length()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_success() {
|
fn test_success() {
|
||||||
let (request, connection) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
let attestation = attestation((request.clone(), connection));
|
let RequestFixture { request, .. } = request_fixture(
|
||||||
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let attestation = attestation_fixture(
|
||||||
|
request.clone(),
|
||||||
|
connection,
|
||||||
|
SignatureAlgId::SECP256K1,
|
||||||
|
encoder_seed().to_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
assert!(request.validate(&attestation).is_ok())
|
assert!(request.validate(&attestation).is_ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrong_signature_alg() {
|
fn test_wrong_signature_alg() {
|
||||||
let (mut request, connection) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
let attestation = attestation((request.clone(), connection));
|
let RequestFixture { mut request, .. } = request_fixture(
|
||||||
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let attestation = attestation_fixture(
|
||||||
|
request.clone(),
|
||||||
|
connection,
|
||||||
|
SignatureAlgId::SECP256K1,
|
||||||
|
encoder_seed().to_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
request.signature_alg = SignatureAlgId::SECP256R1;
|
request.signature_alg = SignatureAlgId::SECP256R1;
|
||||||
|
|
||||||
@@ -208,9 +155,22 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrong_hash_alg() {
|
fn test_wrong_hash_alg() {
|
||||||
let (mut request, connection) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
let attestation = attestation((request.clone(), connection));
|
let RequestFixture { mut request, .. } = request_fixture(
|
||||||
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let attestation = attestation_fixture(
|
||||||
|
request.clone(),
|
||||||
|
connection,
|
||||||
|
SignatureAlgId::SECP256K1,
|
||||||
|
encoder_seed().to_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
request.hash_alg = HashAlgId::SHA256;
|
request.hash_alg = HashAlgId::SHA256;
|
||||||
|
|
||||||
@@ -220,9 +180,22 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrong_server_commitment() {
|
fn test_wrong_server_commitment() {
|
||||||
let (mut request, connection) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
let attestation = attestation((request.clone(), connection));
|
let RequestFixture { mut request, .. } = request_fixture(
|
||||||
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let attestation = attestation_fixture(
|
||||||
|
request.clone(),
|
||||||
|
connection,
|
||||||
|
SignatureAlgId::SECP256K1,
|
||||||
|
encoder_seed().to_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
let ConnectionFixture {
|
let ConnectionFixture {
|
||||||
server_cert_data, ..
|
server_cert_data, ..
|
||||||
@@ -242,9 +215,22 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrong_encoding_commitment_root() {
|
fn test_wrong_encoding_commitment_root() {
|
||||||
let (mut request, connection) = request_and_connection();
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
let attestation = attestation((request.clone(), connection));
|
let RequestFixture { mut request, .. } = request_fixture(
|
||||||
|
transcript,
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let attestation = attestation_fixture(
|
||||||
|
request.clone(),
|
||||||
|
connection,
|
||||||
|
SignatureAlgId::SECP256K1,
|
||||||
|
encoder_seed().to_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
request.encoding_commitment_root = Some(TypedHash {
|
request.encoding_commitment_root = Some(TypedHash {
|
||||||
alg: HashAlgId::BLAKE3,
|
alg: HashAlgId::BLAKE3,
|
||||||
|
|||||||
@@ -611,7 +611,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_get_subsequence(transcript: Transcript) {
|
fn test_transcript_get_subsequence(transcript: Transcript) {
|
||||||
let subseq = transcript
|
let subseq = transcript
|
||||||
.get(Direction::Received, &Idx(RangeSet::from([0..4, 7..10])))
|
.get(Direction::Received, &Idx(RangeSet::from([0..4, 7..10])))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -631,4 +631,207 @@ mod tests {
|
|||||||
let subseq = transcript.get(Direction::Sent, &Idx(RangeSet::from([0..4, 7..10, 11..13])));
|
let subseq = transcript.get(Direction::Sent, &Idx(RangeSet::from([0..4, 7..10, 11..13])));
|
||||||
assert_eq!(subseq, None);
|
assert_eq!(subseq, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_transcript_to_partial_success(transcript: Transcript) {
|
||||||
|
let partial = transcript.to_partial(Idx::new(0..2), Idx::new(3..7));
|
||||||
|
assert_eq!(partial.sent_unsafe(), [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
assert_eq!(
|
||||||
|
partial.received_unsafe(),
|
||||||
|
[0, 0, 0, 3, 4, 5, 6, 0, 0, 0, 0, 0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_transcript_to_partial_failure(transcript: Transcript) {
|
||||||
|
let _ = transcript.to_partial(Idx::new(0..14), Idx::new(3..7));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_partial_transcript_contains(transcript: Transcript) {
|
||||||
|
let partial = transcript.to_partial(Idx::new(0..2), Idx::new(3..7));
|
||||||
|
assert!(partial.contains(Direction::Sent, &Idx::new([0..5, 7..10])));
|
||||||
|
assert!(!partial.contains(Direction::Received, &Idx::new([4..6, 7..13])))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_partial_transcript_unauthed(transcript: Transcript) {
|
||||||
|
let partial = transcript.to_partial(Idx::new(0..2), Idx::new(3..7));
|
||||||
|
assert_eq!(partial.sent_unauthed(), Idx::new(2..12));
|
||||||
|
assert_eq!(partial.received_unauthed(), Idx::new([0..3, 7..12]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_partial_transcript_union_success(transcript: Transcript) {
|
||||||
|
// Non overlapping ranges.
|
||||||
|
let mut simple_partial = transcript.to_partial(Idx::new(0..2), Idx::new(3..7));
|
||||||
|
|
||||||
|
let other_simple_partial = transcript.to_partial(Idx::new(3..5), Idx::new(1..2));
|
||||||
|
|
||||||
|
simple_partial.union_transcript(&other_simple_partial);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
simple_partial.sent_unsafe(),
|
||||||
|
[0, 1, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
simple_partial.received_unsafe(),
|
||||||
|
[0, 1, 0, 3, 4, 5, 6, 0, 0, 0, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(simple_partial.sent_authed(), &Idx::new([0..2, 3..5]));
|
||||||
|
assert_eq!(simple_partial.received_authed(), &Idx::new([1..2, 3..7]));
|
||||||
|
|
||||||
|
// Overwrite with another partial transcript.
|
||||||
|
|
||||||
|
let another_simple_partial = transcript.to_partial(Idx::new(1..4), Idx::new(6..9));
|
||||||
|
|
||||||
|
simple_partial.union_transcript(&another_simple_partial);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
simple_partial.sent_unsafe(),
|
||||||
|
[0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
simple_partial.received_unsafe(),
|
||||||
|
[0, 1, 0, 3, 4, 5, 6, 7, 8, 0, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(simple_partial.sent_authed(), &Idx::new(0..5));
|
||||||
|
assert_eq!(simple_partial.received_authed(), &Idx::new([1..2, 3..9]));
|
||||||
|
|
||||||
|
// Overlapping ranges.
|
||||||
|
let mut overlap_partial = transcript.to_partial(Idx::new(4..6), Idx::new(3..7));
|
||||||
|
|
||||||
|
let other_overlap_partial = transcript.to_partial(Idx::new(3..5), Idx::new(5..9));
|
||||||
|
|
||||||
|
overlap_partial.union_transcript(&other_overlap_partial);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
overlap_partial.sent_unsafe(),
|
||||||
|
[0, 0, 0, 3, 4, 5, 0, 0, 0, 0, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
overlap_partial.received_unsafe(),
|
||||||
|
[0, 0, 0, 3, 4, 5, 6, 7, 8, 0, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(overlap_partial.sent_authed(), &Idx::new([3..5, 4..6]));
|
||||||
|
assert_eq!(overlap_partial.received_authed(), &Idx::new([3..7, 5..9]));
|
||||||
|
|
||||||
|
// Equal ranges.
|
||||||
|
let mut equal_partial = transcript.to_partial(Idx::new(4..6), Idx::new(3..7));
|
||||||
|
|
||||||
|
let other_equal_partial = transcript.to_partial(Idx::new(4..6), Idx::new(3..7));
|
||||||
|
|
||||||
|
equal_partial.union_transcript(&other_equal_partial);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
equal_partial.sent_unsafe(),
|
||||||
|
[0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
equal_partial.received_unsafe(),
|
||||||
|
[0, 0, 0, 3, 4, 5, 6, 0, 0, 0, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(equal_partial.sent_authed(), &Idx::new(4..6));
|
||||||
|
assert_eq!(equal_partial.received_authed(), &Idx::new(3..7));
|
||||||
|
|
||||||
|
// Subset ranges.
|
||||||
|
let mut subset_partial = transcript.to_partial(Idx::new(4..10), Idx::new(3..11));
|
||||||
|
|
||||||
|
let other_subset_partial = transcript.to_partial(Idx::new(6..9), Idx::new(5..6));
|
||||||
|
|
||||||
|
subset_partial.union_transcript(&other_subset_partial);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
subset_partial.sent_unsafe(),
|
||||||
|
[0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 0, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
subset_partial.received_unsafe(),
|
||||||
|
[0, 0, 0, 3, 4, 5, 6, 7, 8, 9, 10, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(subset_partial.sent_authed(), &Idx::new(4..10));
|
||||||
|
assert_eq!(subset_partial.received_authed(), &Idx::new(3..11));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_partial_transcript_union_failure(transcript: Transcript) {
|
||||||
|
let mut partial = transcript.to_partial(Idx::new(4..10), Idx::new(3..11));
|
||||||
|
|
||||||
|
let other_transcript = Transcript::new(
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||||
|
);
|
||||||
|
|
||||||
|
let other_partial = other_transcript.to_partial(Idx::new(6..9), Idx::new(5..6));
|
||||||
|
|
||||||
|
partial.union_transcript(&other_partial);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_partial_transcript_union_subseq_success(transcript: Transcript) {
|
||||||
|
let mut partial = transcript.to_partial(Idx::new(4..10), Idx::new(3..11));
|
||||||
|
let sent_seq = Subsequence::new(Idx::new([0..3, 5..7]), [0, 1, 2, 5, 6].into()).unwrap();
|
||||||
|
let recv_seq = Subsequence::new(Idx::new([0..4, 5..7]), [0, 1, 2, 3, 5, 6].into()).unwrap();
|
||||||
|
|
||||||
|
partial.union_subsequence(Direction::Sent, &sent_seq);
|
||||||
|
partial.union_subsequence(Direction::Received, &recv_seq);
|
||||||
|
|
||||||
|
assert_eq!(partial.sent_unsafe(), [0, 1, 2, 0, 4, 5, 6, 7, 8, 9, 0, 0]);
|
||||||
|
assert_eq!(
|
||||||
|
partial.received_unsafe(),
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0]
|
||||||
|
);
|
||||||
|
assert_eq!(partial.sent_authed(), &Idx::new([0..3, 4..10]));
|
||||||
|
assert_eq!(partial.received_authed(), &Idx::new(0..11));
|
||||||
|
|
||||||
|
// Overwrite with another subseq.
|
||||||
|
let other_sent_seq = Subsequence::new(Idx::new(0..3), [3, 2, 1].into()).unwrap();
|
||||||
|
|
||||||
|
partial.union_subsequence(Direction::Sent, &other_sent_seq);
|
||||||
|
assert_eq!(partial.sent_unsafe(), [3, 2, 1, 0, 4, 5, 6, 7, 8, 9, 0, 0]);
|
||||||
|
assert_eq!(partial.sent_authed(), &Idx::new([0..3, 4..10]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_partial_transcript_union_subseq_failure(transcript: Transcript) {
|
||||||
|
let mut partial = transcript.to_partial(Idx::new(4..10), Idx::new(3..11));
|
||||||
|
|
||||||
|
let sent_seq = Subsequence::new(Idx::new([0..3, 13..15]), [0, 1, 2, 5, 6].into()).unwrap();
|
||||||
|
|
||||||
|
partial.union_subsequence(Direction::Sent, &sent_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_partial_transcript_set_unauthed_range(transcript: Transcript) {
|
||||||
|
let mut partial = transcript.to_partial(Idx::new(4..10), Idx::new(3..7));
|
||||||
|
|
||||||
|
partial.set_unauthed_range(7, Direction::Sent, 2..5);
|
||||||
|
partial.set_unauthed_range(5, Direction::Sent, 0..2);
|
||||||
|
partial.set_unauthed_range(3, Direction::Received, 4..6);
|
||||||
|
partial.set_unauthed_range(1, Direction::Received, 3..7);
|
||||||
|
|
||||||
|
assert_eq!(partial.sent_unsafe(), [5, 5, 7, 7, 4, 5, 6, 7, 8, 9, 0, 0]);
|
||||||
|
assert_eq!(
|
||||||
|
partial.received_unsafe(),
|
||||||
|
[0, 0, 0, 3, 4, 5, 6, 0, 0, 0, 0, 0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_subsequence_new_invalid_len() {
|
||||||
|
let _ = Subsequence::new(Idx::new([0..3, 5..8]), [0, 1, 2, 5, 6].into()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_subsequence_copy_to_invalid_len() {
|
||||||
|
let seq = Subsequence::new(Idx::new([0..3, 5..7]), [0, 1, 2, 5, 6].into()).unwrap();
|
||||||
|
|
||||||
|
let mut data: [u8; 3] = [0, 1, 2];
|
||||||
|
seq.copy_to(&mut data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,3 +182,144 @@ impl From<MerkleError> for EncodingProofError {
|
|||||||
Self::new(ErrorKind::Proof, error)
|
Self::new(ErrorKind::Proof, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use tlsn_data_fixtures::http::{request::POST_JSON, response::OK_JSON};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
fixtures::{encoder_seed, encoding_provider},
|
||||||
|
hash::Blake3,
|
||||||
|
transcript::{encoding::EncodingTree, Idx, Transcript},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
struct EncodingFixture {
|
||||||
|
transcript: Transcript,
|
||||||
|
proof: EncodingProof,
|
||||||
|
commitment: EncodingCommitment,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_encoding_fixture(seed: Vec<u8>) -> EncodingFixture {
|
||||||
|
let transcript = Transcript::new(POST_JSON, OK_JSON);
|
||||||
|
|
||||||
|
let idx_0 = (Direction::Sent, Idx::new(0..POST_JSON.len()));
|
||||||
|
let idx_1 = (Direction::Received, Idx::new(0..OK_JSON.len()));
|
||||||
|
|
||||||
|
let provider = encoding_provider(transcript.sent(), transcript.received());
|
||||||
|
let transcript_length = TranscriptLength {
|
||||||
|
sent: transcript.sent().len() as u32,
|
||||||
|
received: transcript.received().len() as u32,
|
||||||
|
};
|
||||||
|
let tree = EncodingTree::new(
|
||||||
|
&Blake3::default(),
|
||||||
|
[&idx_0, &idx_1],
|
||||||
|
&provider,
|
||||||
|
&transcript_length,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let proof = tree
|
||||||
|
.proof(&transcript, [&idx_0, &idx_1].into_iter())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let commitment = EncodingCommitment {
|
||||||
|
root: tree.root(),
|
||||||
|
seed,
|
||||||
|
};
|
||||||
|
|
||||||
|
EncodingFixture {
|
||||||
|
transcript,
|
||||||
|
proof,
|
||||||
|
commitment,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_encoding_proof_invalid_seed() {
|
||||||
|
let EncodingFixture {
|
||||||
|
transcript,
|
||||||
|
proof,
|
||||||
|
commitment,
|
||||||
|
} = new_encoding_fixture(encoder_seed().to_vec().split_off(1));
|
||||||
|
|
||||||
|
let err = proof
|
||||||
|
.verify_with_provider(
|
||||||
|
&CryptoProvider::default(),
|
||||||
|
&transcript.length(),
|
||||||
|
&commitment,
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
assert!(matches!(err.kind, ErrorKind::Commitment));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_encoding_proof_out_of_range() {
|
||||||
|
let EncodingFixture {
|
||||||
|
transcript,
|
||||||
|
proof,
|
||||||
|
commitment,
|
||||||
|
} = new_encoding_fixture(encoder_seed().to_vec());
|
||||||
|
|
||||||
|
let err = proof
|
||||||
|
.verify_with_provider(
|
||||||
|
&CryptoProvider::default(),
|
||||||
|
&TranscriptLength {
|
||||||
|
sent: (transcript.len_of_direction(Direction::Sent) - 1) as u32,
|
||||||
|
received: (transcript.len_of_direction(Direction::Received) - 2) as u32,
|
||||||
|
},
|
||||||
|
&commitment,
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
assert!(matches!(err.kind, ErrorKind::Proof));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_encoding_proof_tampered_encoding_seq() {
|
||||||
|
let EncodingFixture {
|
||||||
|
transcript,
|
||||||
|
mut proof,
|
||||||
|
commitment,
|
||||||
|
} = new_encoding_fixture(encoder_seed().to_vec());
|
||||||
|
|
||||||
|
let Opening { seq, .. } = proof.openings.values_mut().next().unwrap();
|
||||||
|
|
||||||
|
*seq = Subsequence::new(Idx::new([0..3, 13..15]), [0, 1, 2, 5, 6].into()).unwrap();
|
||||||
|
|
||||||
|
let err = proof
|
||||||
|
.verify_with_provider(
|
||||||
|
&CryptoProvider::default(),
|
||||||
|
&transcript.length(),
|
||||||
|
&commitment,
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
assert!(matches!(err.kind, ErrorKind::Proof));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_encoding_proof_tampered_encoding_blinder() {
|
||||||
|
let EncodingFixture {
|
||||||
|
transcript,
|
||||||
|
mut proof,
|
||||||
|
commitment,
|
||||||
|
} = new_encoding_fixture(encoder_seed().to_vec());
|
||||||
|
|
||||||
|
let Opening { blinder, .. } = proof.openings.values_mut().next().unwrap();
|
||||||
|
|
||||||
|
*blinder = rand::random();
|
||||||
|
|
||||||
|
let err = proof
|
||||||
|
.verify_with_provider(
|
||||||
|
&CryptoProvider::default(),
|
||||||
|
&transcript.length(),
|
||||||
|
&commitment,
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
assert!(matches!(err.kind, ErrorKind::Proof));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -287,6 +287,22 @@ mod tests {
|
|||||||
assert_eq!(partial_transcript.received_unsafe(), transcript.received());
|
assert_eq!(partial_transcript.received_unsafe(), transcript.received());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_encoding_tree_proof_missing_leaf() {
|
||||||
|
let transcript = Transcript::new(POST_JSON, OK_JSON);
|
||||||
|
|
||||||
|
let idx_0 = (Direction::Sent, Idx::new(0..POST_JSON.len()));
|
||||||
|
let idx_1 = (Direction::Received, Idx::new(0..4));
|
||||||
|
let idx_2 = (Direction::Received, Idx::new(4..OK_JSON.len()));
|
||||||
|
|
||||||
|
let tree = new_tree(&transcript, [&idx_0, &idx_1].into_iter()).unwrap();
|
||||||
|
|
||||||
|
let result = tree
|
||||||
|
.proof(&transcript, [&idx_0, &idx_1, &idx_2].into_iter())
|
||||||
|
.unwrap_err();
|
||||||
|
assert!(matches!(result, EncodingTreeError::MissingLeaf { .. }));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_encoding_tree_out_of_bounds() {
|
fn test_encoding_tree_out_of_bounds() {
|
||||||
let transcript = Transcript::new(POST_JSON, OK_JSON);
|
let transcript = Transcript::new(POST_JSON, OK_JSON);
|
||||||
@@ -317,14 +333,5 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
assert!(matches!(result, EncodingTreeError::MissingEncoding { .. }));
|
assert!(matches!(result, EncodingTreeError::MissingEncoding { .. }));
|
||||||
|
|
||||||
let result = EncodingTree::new(
|
|
||||||
&Blake3::default(),
|
|
||||||
[(Direction::Sent, Idx::new(0..8))].iter(),
|
|
||||||
&provider,
|
|
||||||
&transcript_length,
|
|
||||||
)
|
|
||||||
.unwrap_err();
|
|
||||||
assert!(matches!(result, EncodingTreeError::MissingEncoding { .. }));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -357,10 +357,21 @@ impl fmt::Display for TranscriptProofBuilderError {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use tlsn_data_fixtures::http::{request::GET_WITH_HEADER, response::OK_JSON};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
fixtures::{
|
||||||
|
attestation_fixture, encoder_seed, encoding_provider, request_fixture,
|
||||||
|
ConnectionFixture, RequestFixture,
|
||||||
|
},
|
||||||
|
hash::Blake3,
|
||||||
|
signing::SignatureAlgId,
|
||||||
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_range_out_of_bounds() {
|
fn test_reveal_range_out_of_bounds() {
|
||||||
let transcript = Transcript::new(
|
let transcript = Transcript::new(
|
||||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
||||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
||||||
@@ -368,7 +379,83 @@ mod tests {
|
|||||||
let index = Index::default();
|
let index = Index::default();
|
||||||
let mut builder = TranscriptProofBuilder::new(&transcript, None, &index);
|
let mut builder = TranscriptProofBuilder::new(&transcript, None, &index);
|
||||||
|
|
||||||
assert!(builder.reveal(&(10..15), Direction::Sent).is_err());
|
let err = builder.reveal(&(10..15), Direction::Sent).err().unwrap();
|
||||||
assert!(builder.reveal(&(10..15), Direction::Received).is_err());
|
assert!(matches!(err.kind, BuilderErrorKind::Index));
|
||||||
|
|
||||||
|
let err = builder
|
||||||
|
.reveal(&(10..15), Direction::Received)
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
assert!(matches!(err.kind, BuilderErrorKind::Index));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_reveal_missing_encoding_tree() {
|
||||||
|
let transcript = Transcript::new(
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
||||||
|
);
|
||||||
|
let index = Index::default();
|
||||||
|
let mut builder = TranscriptProofBuilder::new(&transcript, None, &index);
|
||||||
|
|
||||||
|
let err = builder.reveal_recv(&(9..11)).err().unwrap();
|
||||||
|
assert!(matches!(err.kind, BuilderErrorKind::MissingCommitment));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_reveal_missing_encoding_commitment_range() {
|
||||||
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
|
let RequestFixture { encoding_tree, .. } = request_fixture(
|
||||||
|
transcript.clone(),
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection,
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let index = Index::default();
|
||||||
|
let mut builder = TranscriptProofBuilder::new(&transcript, Some(&encoding_tree), &index);
|
||||||
|
|
||||||
|
let err = builder.reveal_recv(&(0..11)).err().unwrap();
|
||||||
|
assert!(matches!(err.kind, BuilderErrorKind::MissingCommitment));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_missing_encoding_commitment() {
|
||||||
|
let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON);
|
||||||
|
let connection = ConnectionFixture::tlsnotary(transcript.length());
|
||||||
|
|
||||||
|
let RequestFixture {
|
||||||
|
mut request,
|
||||||
|
encoding_tree,
|
||||||
|
} = request_fixture(
|
||||||
|
transcript.clone(),
|
||||||
|
encoding_provider(GET_WITH_HEADER, OK_JSON),
|
||||||
|
connection.clone(),
|
||||||
|
Blake3::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let index = Index::default();
|
||||||
|
let mut builder = TranscriptProofBuilder::new(&transcript, Some(&encoding_tree), &index);
|
||||||
|
|
||||||
|
builder.reveal_recv(&(0..transcript.len().1)).unwrap();
|
||||||
|
|
||||||
|
let transcript_proof = builder.build().unwrap();
|
||||||
|
|
||||||
|
request.encoding_commitment_root = None;
|
||||||
|
let attestation = attestation_fixture(
|
||||||
|
request,
|
||||||
|
connection,
|
||||||
|
SignatureAlgId::SECP256K1,
|
||||||
|
encoder_seed().to_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let provider = CryptoProvider::default();
|
||||||
|
let err = transcript_proof
|
||||||
|
.verify_with_provider(&provider, &attestation.body)
|
||||||
|
.err()
|
||||||
|
.unwrap();
|
||||||
|
assert!(matches!(err.kind, ErrorKind::Encoding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user