tlsn_core/
fixtures.rs

1//! Fixtures for testing
2
3mod provider;
4
5pub use provider::FixtureEncodingProvider;
6
7use hex::FromHex;
8use p256::ecdsa::SigningKey;
9
10use crate::{
11    attestation::{Attestation, AttestationConfig, Extension},
12    connection::{
13        Certificate, ConnectionInfo, HandshakeData, HandshakeDataV1_2, KeyType, ServerCertData,
14        ServerEphemKey, ServerName, ServerSignature, SignatureScheme, TlsVersion, TranscriptLength,
15    },
16    hash::HashAlgorithm,
17    request::{Request, RequestConfig},
18    signing::SignatureAlgId,
19    transcript::{
20        encoding::{EncoderSecret, EncodingProvider, EncodingTree},
21        Transcript, TranscriptCommitConfigBuilder,
22    },
23    CryptoProvider,
24};
25
26/// A fixture containing various TLS connection data.
27#[derive(Clone)]
28#[allow(missing_docs)]
29pub struct ConnectionFixture {
30    pub server_name: ServerName,
31    pub connection_info: ConnectionInfo,
32    pub server_cert_data: ServerCertData,
33}
34
35impl ConnectionFixture {
36    /// Returns a connection fixture for tlsnotary.org.
37    pub fn tlsnotary(transcript_length: TranscriptLength) -> Self {
38        ConnectionFixture {
39            server_name: ServerName::new("tlsnotary.org".to_string()),
40            connection_info: ConnectionInfo {
41                time: 1671637529,
42                version: TlsVersion::V1_2,
43                transcript_length,
44            },
45            server_cert_data: ServerCertData {
46                certs: vec![
47                    Certificate(include_bytes!("fixtures/data/tlsnotary.org/ee.der").to_vec()),
48                    Certificate(include_bytes!("fixtures/data/tlsnotary.org/inter.der").to_vec()),
49                    Certificate(include_bytes!("fixtures/data/tlsnotary.org/ca.der").to_vec()),
50                ],
51                sig: ServerSignature {
52                    scheme: SignatureScheme::RSA_PKCS1_SHA256,
53                    sig: Vec::<u8>::from_hex(include_bytes!(
54                        "fixtures/data/tlsnotary.org/signature"
55                    ))
56                    .unwrap(),
57                },
58                handshake: HandshakeData::V1_2(HandshakeDataV1_2 {
59                    client_random: <[u8; 32]>::from_hex(include_bytes!(
60                        "fixtures/data/tlsnotary.org/client_random"
61                    ))
62                    .unwrap(),
63                    server_random: <[u8; 32]>::from_hex(include_bytes!(
64                        "fixtures/data/tlsnotary.org/server_random"
65                    ))
66                    .unwrap(),
67                    server_ephemeral_key: ServerEphemKey {
68                        typ: KeyType::SECP256R1,
69                        key: Vec::<u8>::from_hex(include_bytes!(
70                            "fixtures/data/tlsnotary.org/pubkey"
71                        ))
72                        .unwrap(),
73                    },
74                }),
75            },
76        }
77    }
78
79    /// Returns a connection fixture for appliedzkp.org.
80    pub fn appliedzkp(transcript_length: TranscriptLength) -> Self {
81        ConnectionFixture {
82            server_name: ServerName::new("appliedzkp.org".to_string()),
83            connection_info: ConnectionInfo {
84                time: 1671637529,
85                version: TlsVersion::V1_2,
86                transcript_length,
87            },
88            server_cert_data: ServerCertData {
89                certs: vec![
90                    Certificate(include_bytes!("fixtures/data/appliedzkp.org/ee.der").to_vec()),
91                    Certificate(include_bytes!("fixtures/data/appliedzkp.org/inter.der").to_vec()),
92                    Certificate(include_bytes!("fixtures/data/appliedzkp.org/ca.der").to_vec()),
93                ],
94                sig: ServerSignature {
95                    scheme: SignatureScheme::ECDSA_NISTP256_SHA256,
96                    sig: Vec::<u8>::from_hex(include_bytes!(
97                        "fixtures/data/appliedzkp.org/signature"
98                    ))
99                    .unwrap(),
100                },
101                handshake: HandshakeData::V1_2(HandshakeDataV1_2 {
102                    client_random: <[u8; 32]>::from_hex(include_bytes!(
103                        "fixtures/data/appliedzkp.org/client_random"
104                    ))
105                    .unwrap(),
106                    server_random: <[u8; 32]>::from_hex(include_bytes!(
107                        "fixtures/data/appliedzkp.org/server_random"
108                    ))
109                    .unwrap(),
110                    server_ephemeral_key: ServerEphemKey {
111                        typ: KeyType::SECP256R1,
112                        key: Vec::<u8>::from_hex(include_bytes!(
113                            "fixtures/data/appliedzkp.org/pubkey"
114                        ))
115                        .unwrap(),
116                    },
117                }),
118            },
119        }
120    }
121
122    /// Returns the server_ephemeral_key fixture.
123    pub fn server_ephemeral_key(&self) -> &ServerEphemKey {
124        let HandshakeData::V1_2(HandshakeDataV1_2 {
125            server_ephemeral_key,
126            ..
127        }) = &self.server_cert_data.handshake;
128        server_ephemeral_key
129    }
130}
131
132/// Returns an encoding provider fixture.
133pub fn encoding_provider(tx: &[u8], rx: &[u8]) -> impl EncodingProvider {
134    let secret = encoder_secret();
135    FixtureEncodingProvider::new(&secret, Transcript::new(tx, rx))
136}
137
138/// Seed fixture.
139const SEED: [u8; 32] = [0; 32];
140
141/// Delta fixture.
142const DELTA: [u8; 16] = [1; 16];
143
144/// Returns an encoder secret fixture.
145pub fn encoder_secret() -> EncoderSecret {
146    EncoderSecret::new(SEED, DELTA)
147}
148
149/// Returns a tampered encoder secret fixture.
150pub fn encoder_secret_tampered_seed() -> EncoderSecret {
151    let mut seed = SEED;
152    seed[0] += 1;
153    EncoderSecret::new(seed, DELTA)
154}
155
156/// Returns a notary signing key fixture.
157pub fn notary_signing_key() -> SigningKey {
158    SigningKey::from_slice(&[1; 32]).unwrap()
159}
160
161/// A Request fixture used for testing.
162#[allow(missing_docs)]
163pub struct RequestFixture {
164    pub encoding_tree: EncodingTree,
165    pub request: Request,
166}
167
168/// Returns a request fixture for testing.
169pub fn request_fixture(
170    transcript: Transcript,
171    encodings_provider: impl EncodingProvider,
172    connection: ConnectionFixture,
173    encoding_hasher: impl HashAlgorithm,
174    extensions: Vec<Extension>,
175) -> RequestFixture {
176    let provider = CryptoProvider::default();
177    let (sent_len, recv_len) = transcript.len();
178
179    let ConnectionFixture {
180        server_name,
181        server_cert_data,
182        ..
183    } = connection;
184
185    let mut transcript_commitment_builder = TranscriptCommitConfigBuilder::new(&transcript);
186    transcript_commitment_builder
187        .commit_sent(&(0..sent_len))
188        .unwrap()
189        .commit_recv(&(0..recv_len))
190        .unwrap();
191    let transcripts_commitment_config = transcript_commitment_builder.build().unwrap();
192
193    // Prover constructs encoding tree.
194    let encoding_tree = EncodingTree::new(
195        &encoding_hasher,
196        transcripts_commitment_config.iter_encoding(),
197        &encodings_provider,
198        &transcript.length(),
199    )
200    .unwrap();
201
202    let mut builder = RequestConfig::builder();
203
204    for extension in extensions {
205        builder.extension(extension);
206    }
207
208    let request_config = builder.build().unwrap();
209
210    let mut request_builder = Request::builder(&request_config);
211    request_builder
212        .server_name(server_name)
213        .server_cert_data(server_cert_data)
214        .transcript(transcript)
215        .encoding_tree(encoding_tree.clone());
216
217    let (request, _) = request_builder.build(&provider).unwrap();
218
219    RequestFixture {
220        encoding_tree,
221        request,
222    }
223}
224
225/// Returns an attestation fixture for testing.
226pub fn attestation_fixture(
227    request: Request,
228    connection: ConnectionFixture,
229    signature_alg: SignatureAlgId,
230    secret: EncoderSecret,
231) -> Attestation {
232    let ConnectionFixture {
233        connection_info,
234        server_cert_data,
235        ..
236    } = connection;
237
238    let HandshakeData::V1_2(HandshakeDataV1_2 {
239        server_ephemeral_key,
240        ..
241    }) = server_cert_data.handshake;
242
243    let mut provider = CryptoProvider::default();
244    match signature_alg {
245        SignatureAlgId::SECP256K1 => provider.signer.set_secp256k1(&[42u8; 32]).unwrap(),
246        SignatureAlgId::SECP256R1 => provider.signer.set_secp256r1(&[42u8; 32]).unwrap(),
247        _ => unimplemented!(),
248    };
249
250    let attestation_config = AttestationConfig::builder()
251        .supported_signature_algs([signature_alg])
252        .build()
253        .unwrap();
254
255    let mut attestation_builder = Attestation::builder(&attestation_config)
256        .accept_request(request)
257        .unwrap();
258
259    attestation_builder
260        .connection_info(connection_info)
261        .server_ephemeral_key(server_ephemeral_key)
262        .encoder_secret(secret);
263
264    attestation_builder.build(&provider).unwrap()
265}