fix(examples): fix examples for alpha.7 release (#603)

* doc: Fix examples for alpha7 release

+ Use secp256k1 key for notary server fixture
+ fix tower issue
+ Fixed doctes issues (Avoid doc test failures when ignored tests are run)
+ Run wasm tests in incognitto mode to avoid chromiumoxide ws errors

* Added comment

* minor improvements

* formatting

* polish attestation example

* use shorthand fs write

* clean

* simplify discord example

---------

Co-authored-by: sinu <65924192+sinui0@users.noreply.github.com>
This commit is contained in:
Hendrik Eeckhaut
2024-10-03 05:39:47 +02:00
committed by GitHub
parent 6e20930283
commit dfc162929d
22 changed files with 417 additions and 579 deletions

View File

@@ -45,7 +45,7 @@
//! ```no_run //! ```no_run
//! # use tlsn_core::transcript::{TranscriptCommitConfigBuilder, Transcript, Direction}; //! # use tlsn_core::transcript::{TranscriptCommitConfigBuilder, Transcript, Direction};
//! # use tlsn_core::hash::HashAlgId; //! # use tlsn_core::hash::HashAlgId;
//! # fn main() -> Result<(), Box<dyn std::error::Error> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # let transcript: Transcript = unimplemented!(); //! # let transcript: Transcript = unimplemented!();
//! let (sent_len, recv_len) = transcript.len(); //! let (sent_len, recv_len) = transcript.len();
//! //!

View File

@@ -268,6 +268,32 @@ impl<'a> TranscriptProofBuilder<'a> {
self.reveal_with_kind(ranges, direction, self.default_kind) self.reveal_with_kind(ranges, direction, self.default_kind)
} }
/// Reveals the given ranges in the sent transcript using the default kind
/// of commitment.
///
/// # Arguments
///
/// * `ranges` - The ranges to reveal.
pub fn reveal_sent(
&mut self,
ranges: &dyn ToRangeSet<usize>,
) -> Result<&mut Self, TranscriptProofBuilderError> {
self.reveal(ranges, Direction::Sent)
}
/// Reveals the given ranges in the received transcript using the default
/// kind of commitment.
///
/// # Arguments
///
/// * `ranges` - The ranges to reveal.
pub fn reveal_recv(
&mut self,
ranges: &dyn ToRangeSet<usize>,
) -> Result<&mut Self, TranscriptProofBuilderError> {
self.reveal(ranges, Direction::Received)
}
/// Builds the transcript proof. /// Builds the transcript proof.
pub fn build(self) -> Result<TranscriptProof, TranscriptProofBuilderError> { pub fn build(self) -> Result<TranscriptProof, TranscriptProofBuilderError> {
let encoding_proof = if !self.encoding_proof_idxs.is_empty() { let encoding_proof = if !self.encoding_proof_idxs.is_empty() {

View File

@@ -4,7 +4,7 @@ macro_rules! define_fixture {
($name:ident, $doc:tt, $path:tt) => { ($name:ident, $doc:tt, $path:tt) => {
#[doc = $doc] #[doc = $doc]
/// ///
/// ```ignore /// ```text
#[doc = include_str!($path)] #[doc = include_str!($path)]
/// ``` /// ```
pub const $name: &[u8] = include_bytes!($path); pub const $name: &[u8] = include_bytes!($path);

2
crates/examples/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
// Ignore files from examples.
*.tlsn

View File

@@ -9,13 +9,17 @@ notary-client = { workspace = true }
tlsn-common = { workspace = true } tlsn-common = { workspace = true }
tlsn-core = { workspace = true } tlsn-core = { workspace = true }
tlsn-prover = { workspace = true } tlsn-prover = { workspace = true }
tlsn-utils = { workspace = true }
tlsn-verifier = { workspace = true } tlsn-verifier = { workspace = true }
tlsn-formats = { workspace = true }
bincode = { workspace = true }
chrono = { workspace = true } chrono = { workspace = true }
dotenv = { version = "0.15.0" } dotenv = { version = "0.15.0" }
elliptic-curve = { workspace = true, features = ["pkcs8"] } elliptic-curve = { workspace = true, features = ["pkcs8"] }
futures = { workspace = true } futures = { workspace = true }
http-body-util = { workspace = true } http-body-util = { workspace = true }
hex = { workspace = true }
hyper = { workspace = true, features = ["client", "http1"] } hyper = { workspace = true, features = ["client", "http1"] }
hyper-util = { workspace = true, features = ["full"] } hyper-util = { workspace = true, features = ["full"] }
k256 = { workspace = true, features = ["ecdsa"] } k256 = { workspace = true, features = ["ecdsa"] }
@@ -35,12 +39,16 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true } tracing-subscriber = { workspace = true }
[[example]] [[example]]
name = "attestation_prover" name = "attestation_prove"
path = "attestation/prover.rs" path = "attestation/prove.rs"
[[example]] [[example]]
name = "attestation_verifier" name = "attestation_present"
path = "attestation/verifier.rs" path = "attestation/present.rs"
[[example]]
name = "attestation_verify"
path = "attestation/verify.rs"
[[example]] [[example]]
name = "interactive" name = "interactive"
@@ -49,7 +57,3 @@ path = "interactive/interactive.rs"
[[example]] [[example]]
name = "discord_dm" name = "discord_dm"
path = "discord/discord_dm.rs" path = "discord/discord_dm.rs"
[[example]]
name = "discord_dm_verifier"
path = "discord/discord_dm_verifier.rs"

View File

@@ -1,19 +1,16 @@
## Simple Example: Notarize Public Data from example.com (Rust) <a name="rust-simple"></a> ## Simple Attestation Example: Notarize Public Data from example.com (Rust) <a name="rust-simple"></a>
This example demonstrates the simplest possible use case for TLSNotary: This example demonstrates the simplest possible use case for TLSNotary:
1. Notarize: Fetch <https://example.com/> and create a proof of its content. 1. Fetch <https://example.com/> and acquire an attestation of its content.
2. Verify the proof. 2. Create a verifiable presentation using the attestation, while redacting the value of a header.
3. Verify the presentation.
Next, we will redact the content and verify it again:
1. Redact the `USER_AGENT` and titles.
2. Verify the redacted proof.
### 1. Notarize <https://example.com/> ### 1. Notarize <https://example.com/>
Run a simple prover: Run the `prove` binary.
```shell ```shell
cargo run --release --example simple_prover cargo run --release --example attestation_prove
``` ```
If the notarization was successful, you should see this output in the console: If the notarization was successful, you should see this output in the console:
@@ -22,66 +19,54 @@ If the notarization was successful, you should see this output in the console:
Starting an MPC TLS connection with the server Starting an MPC TLS connection with the server
Got a response from the server Got a response from the server
Notarization completed successfully! Notarization completed successfully!
The proof has been written to `simple_proof.json` The attestation has been written to `example.attestation.tlsn` and the corresponding secrets to `example.secrets.tlsn`.
``` ```
⚠️ In this simple example the `Notary` server is automatically started in the background. Note that this is for demonstration purposes only. In a real work example, the notary should be run by a neutral party or the verifier of the proofs. Consult the [Notary Server Docs](https://docs.tlsnotary.org/developers/notary_server.html) for more details on how to run a notary server. ⚠️ In this simple example the `Notary` server is automatically started in the background. Note that this is for demonstration purposes only. In a real world example, the notary should be run by a trusted party. Consult the [Notary Server Docs](https://docs.tlsnotary.org/developers/notary_server.html) for more details on how to run a notary server.
### 2. Verify the Proof ### 2. Build a verifiable presentation
When you open `simple_proof.json` in an editor, you will see a JSON file with lots of non-human-readable byte arrays. You can decode this file by running: This will build a verifiable presentation with the `User-Agent` header redacted from the request. This presentation can be shared with any verifier you wish to present the data to.
Run the `present` binary.
```shell ```shell
cargo run --release --example simple_verifier cargo run --release --example attestation_present
``` ```
This will output the TLS-transaction in clear text: If successful, you should see this output in the console:
```log ```log
Successfully verified that the bytes below came from a session with Dns("example.com") at 2023-11-03 08:48:20 UTC. Presentation built successfully!
Note that the bytes which the Prover chose not to disclose are shown as X. The presentation has been written to `example.presentation.tlsn`.
```
Bytes sent: ### 3. Verify the presentation
This will read the presentation from the previous step, verify it, and print the disclosed data to console.
Run the `verify` binary.
```shell
cargo run --release --example attestation_verify
```
If successful, you should see this output in the console:
```log
Verifying presentation with {key algorithm} key: { hex encoded key }
**Ask yourself, do you trust this key?**
-------------------------------------------------------------------
Successfully verified that the data below came from a session with example.com at 2024-10-03 03:01:40 UTC.
Note that the data which the Prover chose not to disclose are shown as X.
Data sent:
... ...
``` ```
### 3. Redact Information ⚠️ Notice that the presentation comes with a "verifying key". This is the key the Notary used when issuing the attestation that the presentation was built from. If you trust the Notary, or more specifically the verifying key, then you can trust that the presented data is authentic.
Open `simple_prover.rs` and locate the line with:
```rust
let redact = false;
```
and change it to:
```rust
let redact = true;
```
Next, if you run the `simple_prover` and `simple_verifier` again, you'll notice redacted `X`'s in the output:
```shell
cargo run --release --example simple_prover
cargo run --release --example simple_verifier
```
```log
<!doctype html>
<html>
<head>
<title>XXXXXXXXXXXXXX</title>
...
```
You can also use <https://explorer.tlsnotary.org/> to inspect your proofs. Simply drag and drop `simple_proof.json` from your file explorer into the drop zone. Redacted bytes are marked with X characters. [Notary public key](../../notary/server/fixture/notary/notary.pub)
### (Optional) Extra Experiments
Feel free to try these extra challenges:
- [ ] Modify the `server_name` (or any other data) in `simple_proof.json` and verify that the proof is no longer valid.
- [ ] Modify the `build_proof_with_redactions` function in `simple_prover.rs` to redact more or different data.
### Next steps ### Next steps

View File

@@ -0,0 +1,61 @@
// This example demonstrates how to build a verifiable presentation from an
// attestation and the corresponding connection secrets. See the `prove.rs`
// example to learn how to acquire an attestation from a Notary.
use tlsn_core::{attestation::Attestation, presentation::Presentation, CryptoProvider, Secrets};
use tlsn_formats::http::HttpTranscript;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read attestation from disk.
let attestation: Attestation =
bincode::deserialize(&std::fs::read("example.attestation.tlsn")?)?;
// Read secrets from disk.
let secrets: Secrets = bincode::deserialize(&std::fs::read("example.secrets.tlsn")?)?;
// Parse the HTTP transcript.
let transcript = HttpTranscript::parse(secrets.transcript())?;
// Build a transcript proof.
let mut builder = secrets.transcript_proof_builder();
let request = &transcript.requests[0];
// Reveal the structure of the request without the headers or body.
builder.reveal_sent(&request.without_data())?;
// Reveal the request target.
builder.reveal_sent(&request.request.target)?;
// Reveal all headers except the value of the User-Agent header.
for header in &request.headers {
if !header.name.as_str().eq_ignore_ascii_case("User-Agent") {
builder.reveal_sent(header)?;
} else {
builder.reveal_sent(&header.without_value())?;
}
}
// Reveal the entire response.
builder.reveal_recv(&transcript.responses[0])?;
let transcript_proof = builder.build()?;
// Use default crypto provider to build the presentation.
let provider = CryptoProvider::default();
let mut builder = attestation.presentation_builder(&provider);
builder
.identity_proof(secrets.identity_proof())
.transcript_proof(transcript_proof);
let presentation: Presentation = builder.build()?;
// Write the presentation to disk.
std::fs::write(
"example.presentation.tlsn",
bincode::serialize(&presentation)?,
)?;
println!("Presentation built successfully!");
println!("The presentation has been written to `example.presentation.tlsn`.");
Ok(())
}

View File

@@ -0,0 +1,125 @@
// This example demonstrates how to use the Prover to acquire an attestation for
// an HTTP request sent to example.com. The attestation and secrets are saved to
// disk.
use http_body_util::Empty;
use hyper::{body::Bytes, Request, StatusCode};
use hyper_util::rt::TokioIo;
use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt};
use tlsn_common::config::ProtocolConfig;
use tlsn_core::{request::RequestConfig, transcript::TranscriptCommitConfig};
use tlsn_examples::run_notary;
use tlsn_formats::http::{DefaultHttpCommitter, HttpCommit, HttpTranscript};
use tlsn_prover::{Prover, ProverConfig};
// Setting of the application server
const SERVER_DOMAIN: &str = "example.com";
const USER_AGENT: &str = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
let (prover_socket, notary_socket) = tokio::io::duplex(1 << 16);
// Start a local simple notary service
tokio::spawn(run_notary(notary_socket.compat()));
// Prover configuration.
let config = ProverConfig::builder()
.server_name(SERVER_DOMAIN)
.protocol_config(
ProtocolConfig::builder()
// We must configure the amount of data we expect to exchange beforehand, which will
// be preprocessed prior to the connection. Reducing these limits will improve
// performance.
.max_sent_data(1024)
.max_recv_data(4096)
.build()?,
)
.build()?;
// Create a new prover and perform necessary setup.
let prover = Prover::new(config).setup(prover_socket.compat()).await?;
// Open a TCP connection to the server.
let client_socket = tokio::net::TcpStream::connect((SERVER_DOMAIN, 443)).await?;
// Bind the prover to the server connection.
// The returned `mpc_tls_connection` is an MPC TLS connection to the server: all
// data written to/read from it will be encrypted/decrypted using MPC with
// the notary.
let (mpc_tls_connection, prover_fut) = prover.connect(client_socket.compat()).await?;
let mpc_tls_connection = TokioIo::new(mpc_tls_connection.compat());
// Spawn the prover task to be run concurrently in the background.
let prover_task = tokio::spawn(prover_fut);
// Attach the hyper HTTP client to the connection.
let (mut request_sender, connection) =
hyper::client::conn::http1::handshake(mpc_tls_connection).await?;
// Spawn the HTTP task to be run concurrently in the background.
tokio::spawn(connection);
// Build a simple HTTP request with common headers
let request = Request::builder()
.uri("/")
.header("Host", SERVER_DOMAIN)
.header("Accept", "*/*")
// Using "identity" instructs the Server not to use compression for its HTTP response.
// TLSNotary tooling does not support compression.
.header("Accept-Encoding", "identity")
.header("Connection", "close")
.header("User-Agent", USER_AGENT)
.body(Empty::<Bytes>::new())?;
println!("Starting an MPC TLS connection with the server");
// Send the request to the server and wait for the response.
let response = request_sender.send_request(request).await?;
println!("Got a response from the server");
assert!(response.status() == StatusCode::OK);
// The prover task should be done now, so we can await it.
let prover = prover_task.await??;
// Prepare for notarization.
let mut prover = prover.start_notarize();
// Parse the HTTP transcript.
let transcript = HttpTranscript::parse(prover.transcript())?;
// Commit to the transcript.
let mut builder = TranscriptCommitConfig::builder(prover.transcript());
DefaultHttpCommitter::default().commit_transcript(&mut builder, &transcript)?;
prover.transcript_commit(builder.build()?);
// Request an attestation.
let config = RequestConfig::default();
let (attestation, secrets) = prover.finalize(&config).await?;
// Write the attestation to disk.
tokio::fs::write(
"example.attestation.tlsn",
bincode::serialize(&attestation)?,
)
.await?;
// Write the secrets to disk.
tokio::fs::write("example.secrets.tlsn", bincode::serialize(&secrets)?).await?;
println!("Notarization completed successfully!");
println!(
"The attestation has been written to `example.attestation.tlsn` and the \
corresponding secrets to `example.secrets.tlsn`."
);
Ok(())
}

View File

@@ -1,236 +0,0 @@
// Runs a simple Prover which connects to the Notary and notarizes a
// request/response from example.com. The Prover then generates a proof and
// writes it to disk.
use http_body_util::Empty;
use hyper::{body::Bytes, Request, StatusCode};
use hyper_util::rt::TokioIo;
use std::ops::Range;
use tlsn_common::config::ProtocolConfig;
use tlsn_core::proof::TlsProof;
use tokio::io::AsyncWriteExt as _;
use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt};
use tlsn_examples::run_notary;
use tlsn_prover::{state::Notarize, Prover, ProverConfig};
// Setting of the application server
const SERVER_DOMAIN: &str = "example.com";
const USER_AGENT: &str = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36";
use std::str;
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let (prover_socket, notary_socket) = tokio::io::duplex(1 << 16);
// Start a local simple notary service
tokio::spawn(run_notary(notary_socket.compat()));
// Prover configuration.
let config = ProverConfig::builder()
.id("example")
.server_name(SERVER_DOMAIN)
.protocol_config(
ProtocolConfig::builder()
// Configure the limit of the data sent and received.
.max_sent_data(1024)
.max_recv_data(4096)
.build()
.unwrap(),
)
.build()
.unwrap();
// Create a Prover and set it up with the Notary
// This will set up the MPC backend prior to connecting to the server.
let prover = Prover::new(config)
.setup(prover_socket.compat())
.await
.unwrap();
// Connect to the Server via TCP. This is the TLS client socket.
let client_socket = tokio::net::TcpStream::connect((SERVER_DOMAIN, 443))
.await
.unwrap();
// Bind the Prover to the server connection.
// The returned `mpc_tls_connection` is an MPC TLS connection to the Server: all
// data written to/read from it will be encrypted/decrypted using MPC with
// the Notary.
let (mpc_tls_connection, prover_fut) = prover.connect(client_socket.compat()).await.unwrap();
let mpc_tls_connection = TokioIo::new(mpc_tls_connection.compat());
// Spawn the Prover task to be run concurrently
let prover_task = tokio::spawn(prover_fut);
// Attach the hyper HTTP client to the MPC TLS connection
let (mut request_sender, connection) =
hyper::client::conn::http1::handshake(mpc_tls_connection)
.await
.unwrap();
// Spawn the HTTP task to be run concurrently
tokio::spawn(connection);
// Build a simple HTTP request with common headers
let request = Request::builder()
.uri("/")
.header("Host", SERVER_DOMAIN)
.header("Accept", "*/*")
// Using "identity" instructs the Server not to use compression for its HTTP response.
// TLSNotary tooling does not support compression.
.header("Accept-Encoding", "identity")
.header("Connection", "close")
.header("User-Agent", USER_AGENT)
.body(Empty::<Bytes>::new())
.unwrap();
println!("Starting an MPC TLS connection with the server");
// Send the request to the Server and get a response via the MPC TLS connection
let response = request_sender.send_request(request).await.unwrap();
println!("Got a response from the server");
assert!(response.status() == StatusCode::OK);
// The Prover task should be done now, so we can grab the Prover.
let prover = prover_task.await.unwrap().unwrap();
// Prepare for notarization.
let prover = prover.start_notarize();
// Build proof (with or without redactions)
let redact = false;
let proof = if !redact {
build_proof_without_redactions(prover).await
} else {
build_proof_with_redactions(prover).await
};
// Write the proof to a file
let mut file = tokio::fs::File::create("simple_proof.json").await.unwrap();
file.write_all(serde_json::to_string_pretty(&proof).unwrap().as_bytes())
.await
.unwrap();
println!("Notarization completed successfully!");
println!("The proof has been written to `simple_proof.json`");
}
/// Find the ranges of the public and private parts of a sequence.
///
/// Returns a tuple of `(public, private)` ranges.
fn find_ranges(seq: &[u8], private_seq: &[&[u8]]) -> (Vec<Range<usize>>, Vec<Range<usize>>) {
let mut private_ranges = Vec::new();
for s in private_seq {
for (idx, w) in seq.windows(s.len()).enumerate() {
if w == *s {
private_ranges.push(idx..(idx + w.len()));
}
}
}
let mut sorted_ranges = private_ranges.clone();
sorted_ranges.sort_by_key(|r| r.start);
let mut public_ranges = Vec::new();
let mut last_end = 0;
for r in sorted_ranges {
if r.start > last_end {
public_ranges.push(last_end..r.start);
}
last_end = r.end;
}
if last_end < seq.len() {
public_ranges.push(last_end..seq.len());
}
(public_ranges, private_ranges)
}
async fn build_proof_without_redactions(mut prover: Prover<Notarize>) -> TlsProof {
let sent_len = prover.sent_transcript().data().len();
let recv_len = prover.recv_transcript().data().len();
let builder = prover.commitment_builder();
let sent_commitment = builder.commit_sent(&(0..sent_len)).unwrap();
let recv_commitment = builder.commit_recv(&(0..recv_len)).unwrap();
// Finalize, returning the attestation and secrets.
let (attestation, secrets) = prover.finalize().await.unwrap();
// Create a proof for all committed data in this session
let mut proof_builder = notarized_session.data().build_substrings_proof();
// Reveal all the public ranges
proof_builder.reveal_by_id(sent_commitment).unwrap();
proof_builder.reveal_by_id(recv_commitment).unwrap();
let substrings_proof = proof_builder.build().unwrap();
TlsProof {
session: notarized_session.session_proof(),
substrings: substrings_proof,
}
}
async fn build_proof_with_redactions(mut prover: Prover<Notarize>) -> TlsProof {
// Identify the ranges in the outbound data which contain data which we want to
// disclose
let (sent_public_ranges, _) = find_ranges(
prover.sent_transcript().data(),
&[
// Redact the value of the "User-Agent" header. It will NOT be disclosed.
USER_AGENT.as_bytes(),
],
);
// Identify the ranges in the inbound data which contain data which we want to
// disclose
let (recv_public_ranges, _) = find_ranges(
prover.recv_transcript().data(),
&[
// Redact the value of the title. It will NOT be disclosed.
"Example Domain".as_bytes(),
],
);
let builder = prover.commitment_builder();
// Commit to each range of the public outbound data which we want to disclose
let sent_commitments: Vec<_> = sent_public_ranges
.iter()
.map(|range| builder.commit_sent(range).unwrap())
.collect();
// Commit to each range of the public inbound data which we want to disclose
let recv_commitments: Vec<_> = recv_public_ranges
.iter()
.map(|range| builder.commit_recv(range).unwrap())
.collect();
// Finalize, returning the notarized session
let notarized_session = prover.finalize().await.unwrap();
// Create a proof for all committed data in this session
let mut proof_builder = notarized_session.data().build_substrings_proof();
// Reveal all the public ranges
for commitment_id in sent_commitments {
proof_builder.reveal_by_id(commitment_id).unwrap();
}
for commitment_id in recv_commitments {
proof_builder.reveal_by_id(commitment_id).unwrap();
}
let substrings_proof = proof_builder.build().unwrap();
TlsProof {
session: notarized_session.session_proof(),
substrings: substrings_proof,
}
}

View File

@@ -1,77 +0,0 @@
use std::{str, time::Duration};
use elliptic_curve::pkcs8::DecodePublicKey;
use tlsn_core::proof::{SessionProof, TlsProof};
/// A simple verifier which reads a proof generated by `simple_prover.rs` from
/// "proof.json", verifies it and prints the verified data to the console.
fn main() {
// Deserialize the proof
let proof = std::fs::read_to_string("simple_proof.json").unwrap();
let proof: TlsProof = serde_json::from_str(proof.as_str()).unwrap();
let TlsProof {
// The session proof establishes the identity of the server and the commitments
// to the TLS transcript.
session,
// The substrings proof proves select portions of the transcript, while redacting
// anything the Prover chose not to disclose.
substrings,
} = proof;
// Verify the session proof against the Notary's public key
//
// This verifies the identity of the server using a default certificate verifier
// which trusts the root certificates from the `webpki-roots` crate.
session
.verify_with_default_cert_verifier(notary_pubkey())
.unwrap();
let SessionProof {
// The session header that was signed by the Notary is a succinct commitment to the TLS
// transcript.
header,
// This is the session_info, which contains the server_name, that is checked against the
// certificate chain shared in the TLS handshake.
session_info,
..
} = session;
// The time at which the session was recorded
let time = chrono::DateTime::UNIX_EPOCH + Duration::from_secs(header.time());
// Verify the substrings proof against the session header.
//
// This returns the redacted transcripts
let (mut sent, mut recv) = substrings.verify(&header).unwrap();
// Replace the bytes which the Prover chose not to disclose with 'X'
sent.set_redacted(b'X');
recv.set_redacted(b'X');
println!("-------------------------------------------------------------------");
println!(
"Successfully verified that the bytes below came from a session with {:?} at {}.",
session_info.server_name, time
);
println!("Note that the bytes which the Prover chose not to disclose are shown as X.");
println!();
println!("Bytes sent:");
println!();
print!("{}", String::from_utf8(sent.data().to_vec()).unwrap());
println!();
println!("Bytes received:");
println!();
println!("{}", String::from_utf8(recv.data().to_vec()).unwrap());
println!("-------------------------------------------------------------------");
}
/// Returns a Notary pubkey trusted by this Verifier
fn notary_pubkey() -> p256::PublicKey {
let pem_file = str::from_utf8(include_bytes!(
"../../notary/server/fixture/notary/notary.pub"
))
.unwrap();
p256::PublicKey::from_public_key_pem(pem_file).unwrap()
}

View File

@@ -0,0 +1,60 @@
// This example demonstrates how to verify a presentation. See `present.rs` for
// an example of how to build a presentation from an attestation and connection
// secrets.
use std::time::Duration;
use tlsn_core::{
presentation::{Presentation, PresentationOutput},
signing::VerifyingKey,
CryptoProvider,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read the presentation from disk.
let presentation: Presentation =
bincode::deserialize(&std::fs::read("example.presentation.tlsn")?)?;
let provider = CryptoProvider::default();
let VerifyingKey {
alg,
data: key_data,
} = presentation.verifying_key();
println!(
"Verifying presentation with {alg} key: {}\n\n**Ask yourself, do you trust this key?**\n",
hex::encode(key_data)
);
// Verify the presentation.
let PresentationOutput {
server_name,
connection_info,
transcript,
..
} = presentation.verify(&provider).unwrap();
// The time at which the connection was started.
let time = chrono::DateTime::UNIX_EPOCH + Duration::from_secs(connection_info.time);
let server_name = server_name.unwrap();
let mut partial_transcript = transcript.unwrap();
// Set the unauthenticated bytes so they are distinguishable.
partial_transcript.set_unauthed(b'X');
let sent = String::from_utf8_lossy(partial_transcript.sent_unsafe());
let recv = String::from_utf8_lossy(partial_transcript.received_unsafe());
println!("-------------------------------------------------------------------");
println!(
"Successfully verified that the data below came from a session with {server_name} at {time}.",
);
println!("Note that the data which the Prover chose not to disclose are shown as X.\n");
println!("Data sent:\n");
println!("{}\n", sent);
println!("Data received:\n");
println!("{}\n", recv);
println!("-------------------------------------------------------------------");
Ok(())
}

View File

@@ -1,6 +1,6 @@
# Notarize Discord DMs # Notarize Discord DMs
The `discord_dm.rs` example sets up a TLS connection with Discord and notarizes the requested DMs. The notarized session and the proof are written to local JSON files (`discord_dm_notarized_session.json` and `discord_dm_proof.json`) for easier inspection. The `discord_dm.rs` example sets up a TLS connection with Discord and notarizes the requested DMs. The attestation and secrets are saved to disk.
This involves 3 steps: This involves 3 steps:
1. Configure the inputs 1. Configure the inputs
@@ -84,16 +84,6 @@ If the transcript was too long, you may encounter the following error. This occu
thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: IOError(Custom { kind: InvalidData, error: BackendError(DecryptionError("Other: KOSReceiverActor is not setup")) })', /Users/heeckhau/tlsnotary/tlsn/tlsn/tlsn-prover/src/lib.rs:173:50 thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: IOError(Custom { kind: InvalidData, error: BackendError(DecryptionError("Other: KOSReceiverActor is not setup")) })', /Users/heeckhau/tlsnotary/tlsn/tlsn/tlsn-prover/src/lib.rs:173:50
``` ```
# Verifier # Verify
The `discord_dm` example also generated a proof of the transcript with the `Authorization` header redacted from the request, saved in `discord_dm_proof.json`. See the [`present`](../attestation/present.rs) and [`verify`](../attestation/verify.rs) examples for a demonstration of how to construct a presentation and verify it.
We can verify this proof using the `discord_dm_verifier` by running:
```
cargo run --release --example discord_dm_verifier
```
This will verify the proof and print out the redacted transcript!
> **_NOTE:_** <https://explorer.tlsnotary.org/> hosts a generic proof visualizer. Drag and drop your proof into the drop zone to check and render your proof. [Notary public key](../../notary/server/fixture/notary/notary.pub)

View File

@@ -6,13 +6,14 @@ use http_body_util::{BodyExt, Empty};
use hyper::{body::Bytes, Request, StatusCode}; use hyper::{body::Bytes, Request, StatusCode};
use hyper_util::rt::TokioIo; use hyper_util::rt::TokioIo;
use notary_client::{Accepted, NotarizationRequest, NotaryClient}; use notary_client::{Accepted, NotarizationRequest, NotaryClient};
use std::{env, ops::Range, str}; use std::{env, str};
use tlsn_common::config::ProtocolConfig;
use tlsn_core::proof::TlsProof;
use tlsn_prover::{Prover, ProverConfig};
use tokio::io::AsyncWriteExt as _;
use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt}; use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt};
use tracing::debug; use tracing::debug;
use utils::range::RangeSet;
use tlsn_common::config::ProtocolConfig;
use tlsn_core::{request::RequestConfig, transcript::TranscriptCommitConfig};
use tlsn_prover::{Prover, ProverConfig};
// Setting of the application server // Setting of the application server
const SERVER_DOMAIN: &str = "discord.com"; const SERVER_DOMAIN: &str = "discord.com";
@@ -56,12 +57,12 @@ async fn main() {
let Accepted { let Accepted {
io: notary_connection, io: notary_connection,
id: session_id, id: _session_id,
.. ..
} = notary_client } = notary_client
.request_notarization(notarization_request) .request_notarization(notarization_request)
.await .await
.unwrap(); .expect("Could not connect to notary. Make sure it is running.");
// Set up protocol configuration for prover. // Set up protocol configuration for prover.
let protocol_config = ProtocolConfig::builder() let protocol_config = ProtocolConfig::builder()
@@ -70,16 +71,12 @@ async fn main() {
.build() .build()
.unwrap(); .unwrap();
// Configure a new prover with the unique session id returned from notary // Create a new prover and set up the MPC backend.
// client.
let prover_config = ProverConfig::builder() let prover_config = ProverConfig::builder()
.id(session_id)
.server_name(SERVER_DOMAIN) .server_name(SERVER_DOMAIN)
.protocol_config(protocol_config) .protocol_config(protocol_config)
.build() .build()
.unwrap(); .unwrap();
// Create a new prover and set up the MPC backend.
let prover = Prover::new(prover_config) let prover = Prover::new(prover_config)
.setup(notary_connection.compat()) .setup(notary_connection.compat())
.await .await
@@ -143,70 +140,50 @@ async fn main() {
let mut prover = prover.start_notarize(); let mut prover = prover.start_notarize();
// Identify the ranges in the transcript that contain secrets // Identify the ranges in the transcript that contain secrets
let (public_ranges, private_ranges) = let sent_transcript = prover.transcript().sent();
find_ranges(prover.sent_transcript().data(), &[auth_token.as_bytes()]); let recv_transcript = prover.transcript().received();
let recv_len = prover.recv_transcript().data().len(); // Identify the ranges in the outbound data which contain data which we want to
// disclose
let (sent_public_ranges, _) = find_ranges(sent_transcript, &[auth_token.as_bytes()]);
#[allow(clippy::single_range_in_vec_init)]
let recv_public_ranges = RangeSet::from([0..recv_transcript.len()]);
let builder = prover.commitment_builder(); let mut builder = TranscriptCommitConfig::builder(prover.transcript());
// Collect commitment ids for the outbound transcript // Commit to public ranges
let mut commitment_ids = public_ranges builder.commit_sent(&sent_public_ranges).unwrap();
.iter() builder.commit_recv(&recv_public_ranges).unwrap();
.chain(private_ranges.iter())
.map(|range| builder.commit_sent(range).unwrap())
.collect::<Vec<_>>();
// Commit to the full received transcript in one shot, as we don't need to let config = builder.build().unwrap();
// redact anything
commitment_ids.push(builder.commit_recv(&(0..recv_len)).unwrap()); prover.transcript_commit(config);
// Finalize, returning the notarized session // Finalize, returning the notarized session
let notarized_session = prover.finalize().await.unwrap(); let request_config = RequestConfig::default();
let (attestation, secrets) = prover.finalize(&request_config).await.unwrap();
debug!("Notarization complete!"); debug!("Notarization complete!");
// Dump the notarized session to a file tokio::fs::write(
let mut file = tokio::fs::File::create("discord_dm_notarized_session.json") "discord.attestation.tlsn",
.await bincode::serialize(&attestation).unwrap(),
.unwrap();
file.write_all(
serde_json::to_string_pretty(&notarized_session)
.unwrap()
.as_bytes(),
) )
.await .await
.unwrap(); .unwrap();
let session_proof = notarized_session.session_proof(); tokio::fs::write(
"discord.secrets.tlsn",
let mut proof_builder = notarized_session.data().build_substrings_proof(); bincode::serialize(&secrets).unwrap(),
)
// Reveal everything but the auth token (which was assigned commitment id 2) .await
proof_builder.reveal_by_id(commitment_ids[0]).unwrap(); .unwrap();
proof_builder.reveal_by_id(commitment_ids[1]).unwrap();
proof_builder.reveal_by_id(commitment_ids[3]).unwrap();
let substrings_proof = proof_builder.build().unwrap();
let proof = TlsProof {
session: session_proof,
substrings: substrings_proof,
};
// Dump the proof to a file.
let mut file = tokio::fs::File::create("discord_dm_proof.json")
.await
.unwrap();
file.write_all(serde_json::to_string_pretty(&proof).unwrap().as_bytes())
.await
.unwrap();
} }
/// Find the ranges of the public and private parts of a sequence. /// Find the ranges of the public and private parts of a sequence.
/// ///
/// Returns a tuple of `(public, private)` ranges. /// Returns a tuple of `(public, private)` ranges.
fn find_ranges(seq: &[u8], sub_seq: &[&[u8]]) -> (Vec<Range<usize>>, Vec<Range<usize>>) { fn find_ranges(seq: &[u8], sub_seq: &[&[u8]]) -> (RangeSet<usize>, RangeSet<usize>) {
let mut private_ranges = Vec::new(); let mut private_ranges = Vec::new();
for s in sub_seq { for s in sub_seq {
for (idx, w) in seq.windows(s.len()).enumerate() { for (idx, w) in seq.windows(s.len()).enumerate() {
@@ -232,5 +209,8 @@ fn find_ranges(seq: &[u8], sub_seq: &[&[u8]]) -> (Vec<Range<usize>>, Vec<Range<u
public_ranges.push(last_end..seq.len()); public_ranges.push(last_end..seq.len());
} }
(public_ranges, private_ranges) (
RangeSet::from(public_ranges),
RangeSet::from(private_ranges),
)
} }

View File

@@ -1,78 +0,0 @@
use std::{str, time::Duration};
use elliptic_curve::pkcs8::DecodePublicKey;
use tlsn_core::proof::{SessionProof, TlsProof};
/// A simple verifier which reads a proof generated by `discord_dm.rs` from
/// "discord_dm_proof.json", verifies it and prints the verified data to the
/// console.
fn main() {
// Deserialize the proof
let proof = std::fs::read_to_string("discord_dm_proof.json").unwrap();
let proof: TlsProof = serde_json::from_str(proof.as_str()).unwrap();
let TlsProof {
// The session proof establishes the identity of the server and the commitments
// to the TLS transcript.
session,
// The substrings proof proves select portions of the transcript, while redacting
// anything the Prover chose not to disclose.
substrings,
} = proof;
// Verify the session proof against the Notary's public key
//
// This verifies the identity of the server using a default certificate verifier
// which trusts the root certificates from the `webpki-roots` crate.
session
.verify_with_default_cert_verifier(notary_pubkey())
.unwrap();
let SessionProof {
// The session header that was signed by the Notary is a succinct commitment to the TLS
// transcript.
header,
// This is the session_info, which contains the server_name, that is checked against the
// certificate chain shared in the TLS handshake.
session_info,
..
} = session;
// The time at which the session was recorded
let time = chrono::DateTime::UNIX_EPOCH + Duration::from_secs(header.time());
// Verify the substrings proof against the session header.
//
// This returns the redacted transcripts
let (mut sent, mut recv) = substrings.verify(&header).unwrap();
// Replace the bytes which the Prover chose not to disclose with 'X'
sent.set_redacted(b'X');
recv.set_redacted(b'X');
println!("-------------------------------------------------------------------");
println!(
"Successfully verified that the bytes below came from a session with {:?} at {}.",
session_info.server_name, time
);
println!("Note that the bytes which the Prover chose not to disclose are shown as X.");
println!();
println!("Bytes sent:");
println!();
print!("{}", String::from_utf8(sent.data().to_vec()).unwrap());
println!();
println!("Bytes received:");
println!();
println!("{}", String::from_utf8(recv.data().to_vec()).unwrap());
println!("-------------------------------------------------------------------");
}
/// Returns a Notary pubkey trusted by this Verifier
fn notary_pubkey() -> p256::PublicKey {
let pem_file = str::from_utf8(include_bytes!(
"../../notary/server/fixture/notary/notary.pub"
))
.unwrap();
p256::PublicKey::from_public_key_pem(pem_file).unwrap()
}

View File

@@ -2,9 +2,9 @@ use http_body_util::Empty;
use hyper::{body::Bytes, Request, StatusCode, Uri}; use hyper::{body::Bytes, Request, StatusCode, Uri};
use hyper_util::rt::TokioIo; use hyper_util::rt::TokioIo;
use tlsn_common::config::{ProtocolConfig, ProtocolConfigValidator}; use tlsn_common::config::{ProtocolConfig, ProtocolConfigValidator};
use tlsn_core::{proof::SessionInfo, Direction, RedactedTranscript}; use tlsn_core::transcript::Idx;
use tlsn_prover::{state::Prove, Prover, ProverConfig}; use tlsn_prover::{state::Prove, Prover, ProverConfig};
use tlsn_verifier::tls::{Verifier, VerifierConfig}; use tlsn_verifier::{SessionInfo, Verifier, VerifierConfig};
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt}; use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt};
use tracing::instrument; use tracing::instrument;
@@ -31,13 +31,10 @@ async fn main() {
let (_, (sent, received, _session_info)) = tokio::join!(prover, verifier); let (_, (sent, received, _session_info)) = tokio::join!(prover, verifier);
println!("Successfully verified {}", &uri); println!("Successfully verified {}", &uri);
println!( println!("Verified sent data:\n{}", bytes_to_redacted_string(&sent));
"Verified sent data:\n{}",
bytes_to_redacted_string(sent.data())
);
println!( println!(
"Verified received data:\n{}", "Verified received data:\n{}",
bytes_to_redacted_string(received.data()) bytes_to_redacted_string(&received)
); );
} }
@@ -57,7 +54,6 @@ async fn prover<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
// Perform the setup phase with the verifier. // Perform the setup phase with the verifier.
let prover = Prover::new( let prover = Prover::new(
ProverConfig::builder() ProverConfig::builder()
.id(id)
.server_name(server_domain) .server_name(server_domain)
.protocol_config( .protocol_config(
ProtocolConfig::builder() ProtocolConfig::builder()
@@ -112,9 +108,12 @@ async fn prover<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
// Create proof for the Verifier. // Create proof for the Verifier.
let mut prover = prover_task.await.unwrap().unwrap().start_prove(); let mut prover = prover_task.await.unwrap().unwrap().start_prove();
redact_and_reveal_received_data(&mut prover);
redact_and_reveal_sent_data(&mut prover); let idx_sent = redact_and_reveal_sent_data(&mut prover);
prover.prove().await.unwrap(); let idx_recv = redact_and_reveal_received_data(&mut prover);
// Reveal parts of the transcript
prover.prove_transcript(idx_sent, idx_recv).await.unwrap();
// Finalize. // Finalize.
prover.finalize().await.unwrap() prover.finalize().await.unwrap()
@@ -124,7 +123,7 @@ async fn prover<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
async fn verifier<T: AsyncWrite + AsyncRead + Send + Sync + Unpin + 'static>( async fn verifier<T: AsyncWrite + AsyncRead + Send + Sync + Unpin + 'static>(
socket: T, socket: T,
id: &str, id: &str,
) -> (RedactedTranscript, RedactedTranscript, SessionInfo) { ) -> (Vec<u8>, Vec<u8>, SessionInfo) {
// Setup Verifier. // Setup Verifier.
let config_validator = ProtocolConfigValidator::builder() let config_validator = ProtocolConfigValidator::builder()
.max_sent_data(MAX_SENT_DATA) .max_sent_data(MAX_SENT_DATA)
@@ -133,24 +132,25 @@ async fn verifier<T: AsyncWrite + AsyncRead + Send + Sync + Unpin + 'static>(
.unwrap(); .unwrap();
let verifier_config = VerifierConfig::builder() let verifier_config = VerifierConfig::builder()
.id(id)
.protocol_config_validator(config_validator) .protocol_config_validator(config_validator)
.build() .build()
.unwrap(); .unwrap();
let verifier = Verifier::new(verifier_config); let verifier = Verifier::new(verifier_config);
// Verify MPC-TLS and wait for (redacted) data. // Verify MPC-TLS and wait for (redacted) data.
let (sent, received, session_info) = verifier.verify(socket.compat()).await.unwrap(); let (mut partial_transcript, session_info) = verifier.verify(socket.compat()).await.unwrap();
partial_transcript.set_unauthed(0);
// Check sent data: check host. // Check sent data: check host.
let sent_data = String::from_utf8(sent.data().to_vec()).expect("Verifier expected sent data"); let sent = partial_transcript.sent_unsafe().to_vec();
let sent_data = String::from_utf8(sent.clone()).expect("Verifier expected sent data");
sent_data sent_data
.find(SERVER_DOMAIN) .find(SERVER_DOMAIN)
.unwrap_or_else(|| panic!("Verification failed: Expected host {}", SERVER_DOMAIN)); .unwrap_or_else(|| panic!("Verification failed: Expected host {}", SERVER_DOMAIN));
// Check received data: check json and version number. // Check received data: check json and version number.
let response = let received = partial_transcript.received_unsafe().to_vec();
String::from_utf8(received.data().to_vec()).expect("Verifier expected received data"); let response = String::from_utf8(received.clone()).expect("Verifier expected received data");
response response
.find("Example Domain") .find("Example Domain")
.expect("Expected valid data from example.com"); .expect("Expected valid data from example.com");
@@ -162,35 +162,35 @@ async fn verifier<T: AsyncWrite + AsyncRead + Send + Sync + Unpin + 'static>(
} }
/// Redacts and reveals received data to the verifier. /// Redacts and reveals received data to the verifier.
fn redact_and_reveal_received_data(prover: &mut Prover<Prove>) { fn redact_and_reveal_received_data(prover: &mut Prover<Prove>) -> Idx {
let recv_transcript_len = prover.recv_transcript().data().len(); let recv_transcript = prover.transcript().received();
let recv_transcript_len = recv_transcript.len();
// Get the received data as a string. // Get the received data as a string.
let received_string = String::from_utf8(prover.recv_transcript().data().to_vec()).unwrap(); let received_string = String::from_utf8(recv_transcript.to_vec()).unwrap();
// Find the substring "illustrative". // Find the substring "illustrative".
let start = received_string let start = received_string
.find("illustrative") .find("illustrative")
.expect("Error: The substring 'illustrative' was not found in the received data."); .expect("Error: The substring 'illustrative' was not found in the received data.");
let end = start + "illustrative".len(); let end = start + "illustrative".len();
// Reveal everything except for the substring "illustrative". Idx::new([0..start, end..recv_transcript_len])
_ = prover.reveal(0..start, Direction::Received);
_ = prover.reveal(end..recv_transcript_len, Direction::Received);
} }
/// Redacts and reveals sent data to the verifier. /// Redacts and reveals sent data to the verifier.
fn redact_and_reveal_sent_data(prover: &mut Prover<Prove>) { fn redact_and_reveal_sent_data(prover: &mut Prover<Prove>) -> Idx {
let sent_transcript_len = prover.sent_transcript().data().len(); let sent_transcript = prover.transcript().sent();
let sent_transcript_len = sent_transcript.len();
let sent_string = String::from_utf8(sent_transcript.to_vec()).unwrap();
let sent_string = String::from_utf8(prover.sent_transcript().data().to_vec()).unwrap();
let secret_start = sent_string.find(SECRET).unwrap(); let secret_start = sent_string.find(SECRET).unwrap();
// Reveal everything except for the SECRET. // Reveal everything except for the SECRET.
_ = prover.reveal(0..secret_start, Direction::Sent); Idx::new([
_ = prover.reveal( 0..secret_start,
secret_start + SECRET.len()..sent_transcript_len, secret_start + SECRET.len()..sent_transcript_len,
Direction::Sent, ])
);
} }
/// Render redacted bytes as `🙈`. /// Render redacted bytes as `🙈`.

View File

@@ -1,4 +1,5 @@
use futures::{AsyncRead, AsyncWrite}; use futures::{AsyncRead, AsyncWrite};
use k256::{pkcs8::DecodePrivateKey, SecretKey};
use tlsn_common::config::ProtocolConfigValidator; use tlsn_common::config::ProtocolConfigValidator;
use tlsn_core::{attestation::AttestationConfig, signing::SignatureAlgId, CryptoProvider}; use tlsn_core::{attestation::AttestationConfig, signing::SignatureAlgId, CryptoProvider};
use tlsn_verifier::{Verifier, VerifierConfig}; use tlsn_verifier::{Verifier, VerifierConfig};
@@ -13,8 +14,11 @@ const MAX_RECV_DATA: usize = 1 << 14;
/// Runs a simple Notary with the provided connection to the Prover. /// Runs a simple Notary with the provided connection to the Prover.
pub async fn run_notary<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(conn: T) { pub async fn run_notary<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(conn: T) {
let pem_data = include_str!("../../notary/server/fixture/notary/notary.key");
let secret_key = SecretKey::from_pkcs8_pem(pem_data).unwrap().to_bytes();
let mut provider = CryptoProvider::default(); let mut provider = CryptoProvider::default();
provider.signer.set_secp256k1(NOTARY_PRIVATE_KEY).unwrap(); provider.signer.set_secp256k1(&secret_key).unwrap();
// Setup the config. Normally a different ID would be generated // Setup the config. Normally a different ID would be generated
// for each notarization. // for each notarization.

View File

@@ -43,6 +43,7 @@ tokio-util = { workspace = true, features = ["compat"] }
tower = { version = "0.4", features = ["make"] } tower = { version = "0.4", features = ["make"] }
tower-http = { version = "0.5", features = ["cors"] } tower-http = { version = "0.5", features = ["cors"] }
tower-service = { version = "0.3" } tower-service = { version = "0.3" }
tower-util = { version = "0.3.1" }
tracing = { workspace = true } tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter"] } tracing-subscriber = { workspace = true, features = ["env-filter"] }
uuid = { workspace = true, features = ["v4", "fast-rng"] } uuid = { workspace = true, features = ["v4", "fast-rng"] }

View File

@@ -1,5 +1,5 @@
-----BEGIN PRIVATE KEY----- -----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgEvBc/VMWn3E4PGfe MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgbGCmm+WHxwlKKKRWddfO
ETc/ekdTRmRwNN9J6eKDPxJ98ZmhRANCAAQG/foUjhkWzMlrQNAUnfBYJe9UsWtx 02TmpM787BJQuoVrHeCI5v6hRANCAAR7SPGcE5toiPteODpNcsIzUYb9WFjnrnQ6
HMwbmRpN4cahLMO7pwWrHe4RZikUajoLQQ5SB/6YSBuS0utehy/nIfMq tL+OBxsG5+j9AN8W8v+KvMi/UlKaEaJVywIcLCiWENdZyB7u/Yix
-----END PRIVATE KEY----- -----END PRIVATE KEY-----

View File

@@ -1,4 +1,4 @@
-----BEGIN PUBLIC KEY----- -----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBv36FI4ZFszJa0DQFJ3wWCXvVLFr MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEe0jxnBObaIj7Xjg6TXLCM1GG/VhY5650
cRzMG5kaTeHGoSzDu6cFqx3uEWYpFGo6C0EOUgf+mEgbktLrXocv5yHzKg== OrS/jgcbBufo/QDfFvL/irzIv1JSmhGiVcsCHCwolhDXWcge7v2IsQ==
-----END PUBLIC KEY----- -----END PUBLIC KEY-----

View File

@@ -898,7 +898,8 @@ mod tests {
use super::*; use super::*;
use axum::{body::Body, routing::get, Router}; use axum::{body::Body, routing::get, Router};
use http::{Request, Version}; use http::{Request, Version};
use tower::ServiceExt; // NOTARY_MODIFICATION: use tower_util instead of tower to make clippy happy
use tower_util::ServiceExt;
#[tokio::test] #[tokio::test]
async fn rejects_http_1_0_requests() { async fn rejects_http_1_0_requests() {

View File

@@ -15,10 +15,7 @@ use std::{string::String, time::Duration};
use tls_core::verify::WebPkiVerifier; use tls_core::verify::WebPkiVerifier;
use tls_server_fixture::{bind_test_server_hyper, CA_CERT_DER, SERVER_DOMAIN}; use tls_server_fixture::{bind_test_server_hyper, CA_CERT_DER, SERVER_DOMAIN};
use tlsn_common::config::ProtocolConfig; use tlsn_common::config::ProtocolConfig;
use tlsn_core::{ use tlsn_core::{request::RequestConfig, transcript::TranscriptCommitConfig, CryptoProvider};
request::RequestConfig, signing::SignatureAlgId, transcript::TranscriptCommitConfig,
CryptoProvider,
};
use tlsn_prover::{Prover, ProverConfig}; use tlsn_prover::{Prover, ProverConfig};
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt}; use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt};
@@ -260,11 +257,7 @@ async fn test_tcp_prover<S: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
prover.transcript_commit(commit_config); prover.transcript_commit(commit_config);
let mut request_builder = RequestConfig::builder(); let request = RequestConfig::builder().build().unwrap();
request_builder.signature_alg(SignatureAlgId::SECP256R1);
let request = request_builder.build().unwrap();
_ = prover.finalize(&request).await.unwrap(); _ = prover.finalize(&request).await.unwrap();
@@ -453,11 +446,7 @@ async fn test_websocket_prover() {
prover.transcript_commit(commit_config); prover.transcript_commit(commit_config);
let mut request_builder = RequestConfig::builder(); let request = RequestConfig::builder().build().unwrap();
request_builder.signature_alg(SignatureAlgId::SECP256R1);
let request = request_builder.build().unwrap();
_ = prover.finalize(&request).await.unwrap(); _ = prover.finalize(&request).await.unwrap();

View File

@@ -16,6 +16,7 @@ use crate::{TestResult, DEFAULT_SERVER_IP, DEFAULT_WASM_PORT};
pub async fn run() -> Result<Vec<TestResult>> { pub async fn run() -> Result<Vec<TestResult>> {
let config = BrowserConfig::builder() let config = BrowserConfig::builder()
.request_timeout(Duration::from_secs(60)) .request_timeout(Duration::from_secs(60))
.incognito() // Run in incognito mode to avoid unexplained WS connection errors in chromiumoxide.
.build() .build()
.map_err(|s| anyhow!(s))?; .map_err(|s| anyhow!(s))?;