reach_attestant/
net.rs

1// SPDX-FileCopyrightText: 2025 eaon <eaon@posteo.net>
2// SPDX-License-Identifier: EUPL-1.2
3
4use rand_core::CryptoRngCore;
5
6use reach_core::{
7    AssureAuthentication,
8    memory::rng,
9    wire::{AttestantVerifyingKeys, InitAuthenticatedSession, ReachCommunication},
10};
11use reach_websocket::{
12    WebSocketClient, WebSocketError, WebSocketRemoteClientOptions, websocketstream_from_request,
13};
14
15use crate::cli_utils::MayBail;
16use crate::memory::AttestantSigningKeys;
17
18pub type ReachClient = WebSocketClient<ReachCommunication>;
19pub type ReachClientOptions<S, R> = WebSocketRemoteClientOptions<S, R>;
20
21pub async fn create<const B: usize, R>(url: &str, csprng: &R) -> Result<ReachClient, WebSocketError>
22where
23    R: CryptoRngCore + Clone + Send + 'static,
24{
25    websocketstream_from_request(url).await.map(|web_socket| {
26        ReachClient::from(ReachClientOptions::new(
27            web_socket,
28            vec![1000, 2000, 4000, 8000],
29            csprng.clone(),
30        ))
31    })
32}
33
34pub async fn authenticate(
35    attestant_signing_keys: &AttestantSigningKeys,
36    attestant_verifying_keys: &AttestantVerifyingKeys,
37    url: &str,
38) -> ReachClient {
39    let mut csprng = rng::<8192>().expect("should initialize random number generator");
40
41    let mut client = create::<10, _>(&url.replace("http", "ws"), &csprng)
42        .await
43        .map_err(|_| "Could not initiate client session. Is the server online?")
44        .may_bail(true);
45
46    let challenge = client
47        .send_and_wait(&InitAuthenticatedSession(0))
48        .await
49        .map_err(|_| "Did not receive an authentication challenge as expected…")
50        .may_bail(true);
51
52    let assurance = attestant_signing_keys.assure_authentication(
53        attestant_verifying_keys,
54        &challenge,
55        &mut csprng,
56    );
57
58    client
59        .send_and_wait(&assurance)
60        .await
61        .map(|_| client)
62        .map_err(|_| "Authentication failed.")
63        .may_bail(true)
64}