ordinary-auth 0.6.0

Auth for Ordinary
Documentation
// Copyright (C) 2026 Ordinary Labs, LLC.
//
// SPDX-License-Identifier: AGPL-3.0-only

use crate::DefaultCipherSuite;
use anyhow::bail;

use bytes::Bytes;
#[cfg(feature = "client")]
use opaque_ke::{ClientRegistration, ClientRegistrationFinishParameters, RegistrationResponse};
#[cfg(feature = "core")]
use opaque_ke::{RegistrationRequest, RegistrationUpload, ServerRegistration, ServerSetup};

#[cfg(feature = "client")]
use chacha20poly1305::aead::OsRng;

/// message
#[cfg(feature = "core")]
pub fn server_start(
    setup: &ServerSetup<DefaultCipherSuite>,
    account: &[u8],
    client_start: &[u8],
) -> anyhow::Result<Bytes> {
    match ServerRegistration::<DefaultCipherSuite>::start(
        setup,
        RegistrationRequest::deserialize(client_start)?,
        account,
    ) {
        Ok(start_result) => Ok(Bytes::copy_from_slice(
            &start_result.message.serialize()[..],
        )),
        Err(err) => bail!("{err}"),
    }
}

/// `password_file`
#[cfg(feature = "core")]
pub fn server_finish(client_finish: &[u8]) -> anyhow::Result<Vec<u8>> {
    let registration_upload = RegistrationUpload::<DefaultCipherSuite>::deserialize(client_finish)?;

    let password_file = ServerRegistration::finish(registration_upload);

    Ok(password_file.serialize().to_vec())
}

/// (state, message)
#[cfg(feature = "client")]
pub fn client_start(password: &[u8]) -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
    let mut rng = OsRng;
    match ClientRegistration::<DefaultCipherSuite>::start(&mut rng, password) {
        Ok(start) => Ok((
            start.state.serialize().to_vec(),
            start.message.serialize().to_vec(),
        )),
        Err(err) => bail!("{err}"),
    }
}

/// message
#[cfg(feature = "client")]
pub fn client_finish(
    password: &[u8],
    client_state: &[u8],
    server_message: &[u8],
) -> anyhow::Result<Bytes> {
    let client_state = match ClientRegistration::<DefaultCipherSuite>::deserialize(client_state) {
        Ok(s) => s,
        Err(err) => bail!("{err}"),
    };

    let mut rng = OsRng;

    match client_state.finish(
        &mut rng,
        password,
        RegistrationResponse::deserialize(server_message)?,
        ClientRegistrationFinishParameters::default(),
    ) {
        Ok(finish) => Ok(Bytes::copy_from_slice(&finish.message.serialize()[..])),
        Err(err) => bail!("{err}"),
    }
}