Skip to main content

openmls/test_utils/
mod.rs

1//! Test utilities
2#![allow(dead_code)]
3#![allow(unused_imports)]
4
5use std::{
6    fmt::Write as FmtWrite,
7    fs::File,
8    io::{BufReader, Write},
9};
10
11use openmls_basic_credential::SignatureKeyPair;
12pub use openmls_traits::{
13    storage::StorageProvider as StorageProviderTrait,
14    types::{Ciphersuite, HpkeKeyPair},
15    OpenMlsProvider,
16};
17use serde::{self, de::DeserializeOwned, Serialize};
18
19#[cfg(test)]
20use crate::group::tests_and_kats::utils::CredentialWithKeyAndSigner;
21pub use crate::utils::*;
22use crate::{
23    ciphersuite::{HpkePrivateKey, OpenMlsSignaturePublicKey},
24    credentials::{Credential, CredentialType, CredentialWithKey},
25    key_packages::{KeyPackage, KeyPackageBuilder},
26    prelude::KeyPackageBundle,
27    treesync::node::encryption_keys::{EncryptionKeyPair, EncryptionPrivateKey},
28};
29
30pub mod frankenstein;
31pub mod restricted_provider;
32pub mod storage_state;
33pub mod test_framework;
34
35pub mod single_group_test_framework;
36
37pub(crate) fn write(file_name: &str, obj: impl Serialize) {
38    let mut file = match File::create(file_name) {
39        Ok(f) => f,
40        Err(_) => panic!("Couldn't open file {file_name}."),
41    };
42    file.write_all(
43        serde_json::to_string_pretty(&obj)
44            .expect("Error serializing test vectors")
45            .as_bytes(),
46    )
47    .expect("Error writing test vector file");
48}
49
50// the macro is used in other files, suppress false positive
51#[allow(unused_macros)]
52macro_rules! read_json {
53    ($file_name:expr) => {{
54        let data = include_str!($file_name);
55        serde_json::from_str(data).expect(&format!("Error reading file {}", $file_name))
56    }};
57}
58
59pub(crate) fn read<T: DeserializeOwned>(file_name: &str) -> T {
60    let file = match File::open(file_name) {
61        Ok(f) => f,
62        Err(_) => panic!("Couldn't open file {file_name}."),
63    };
64    let reader = BufReader::new(file);
65    match serde_json::from_reader(reader) {
66        Ok(r) => r,
67        Err(e) => panic!("Error reading file.\n{e:?}"),
68    }
69}
70
71/// Convert `bytes` to a hex string.
72pub fn bytes_to_hex(bytes: &[u8]) -> String {
73    let mut hex = String::new();
74    for &b in bytes {
75        write!(&mut hex, "{b:02X}").expect("Unable to write to string");
76    }
77    hex
78}
79
80/// Convert a hex string to a byte vector.
81pub fn hex_to_bytes(hex: &str) -> Vec<u8> {
82    assert!(hex.len().is_multiple_of(2));
83    let mut bytes = Vec::new();
84    for i in 0..(hex.len() / 2) {
85        bytes.push(
86            u8::from_str_radix(&hex[2 * i..2 * i + 2], 16).expect("An unexpected error occurred."),
87        );
88    }
89    bytes
90}
91
92/// Convert a hex string to a byte vector.
93/// If the input is `None`, this returns an empty vector.
94pub fn hex_to_bytes_option(hex: Option<String>) -> Vec<u8> {
95    match hex {
96        Some(s) => hex_to_bytes(&s),
97        None => vec![],
98    }
99}
100
101// === Convenience functions ===
102
103#[cfg(test)]
104pub(crate) struct GroupCandidate {
105    pub identity: Vec<u8>,
106    pub key_package: KeyPackageBundle,
107    pub signature_keypair: SignatureKeyPair,
108    pub credential_with_key_and_signer: CredentialWithKeyAndSigner,
109}
110
111#[cfg(test)]
112pub(crate) fn generate_group_candidate(
113    identity: &[u8],
114    ciphersuite: Ciphersuite,
115    provider: &impl OpenMlsProvider,
116    use_store: bool,
117) -> GroupCandidate {
118    use crate::{credentials::BasicCredential, prelude::KeyPackageBundle};
119
120    let credential_with_key_and_signer = {
121        let credential = BasicCredential::new(identity.to_vec());
122
123        let signature_keypair = SignatureKeyPair::new(ciphersuite.signature_algorithm()).unwrap();
124
125        // Store if there is a key store.
126        if use_store {
127            signature_keypair.store(provider.storage()).unwrap();
128        }
129
130        let signature_pkey = OpenMlsSignaturePublicKey::new(
131            signature_keypair.to_public_vec().into(),
132            ciphersuite.signature_algorithm(),
133        )
134        .unwrap();
135
136        CredentialWithKeyAndSigner {
137            credential_with_key: CredentialWithKey {
138                credential: credential.into(),
139                signature_key: signature_pkey.into(),
140            },
141            signer: signature_keypair,
142        }
143    };
144
145    let key_package = {
146        let builder = KeyPackageBuilder::new();
147
148        if use_store {
149            builder
150                .build(
151                    ciphersuite,
152                    provider,
153                    &credential_with_key_and_signer.signer,
154                    credential_with_key_and_signer.credential_with_key.clone(),
155                )
156                .unwrap()
157        } else {
158            // We don't want to store anything. So...
159            let provider = OpenMlsRustCrypto::default();
160
161            let key_package_creation_result = builder
162                .build_without_storage(
163                    ciphersuite,
164                    &provider,
165                    &credential_with_key_and_signer.signer,
166                    credential_with_key_and_signer.credential_with_key.clone(),
167                )
168                .unwrap();
169
170            KeyPackageBundle::new(
171                key_package_creation_result.key_package,
172                key_package_creation_result.init_private_key,
173                key_package_creation_result
174                    .encryption_keypair
175                    .private_key()
176                    .clone(),
177            )
178        }
179    };
180
181    GroupCandidate {
182        identity: identity.to_vec(),
183        key_package,
184        signature_keypair: credential_with_key_and_signer.signer.clone(),
185        credential_with_key_and_signer,
186    }
187}
188
189#[cfg(all(
190    feature = "libcrux-provider",
191    not(any(
192        target_arch = "wasm32",
193        all(target_arch = "x86", target_os = "windows")
194    ))
195))]
196pub type OpenMlsLibcrux = openmls_libcrux_crypto::Provider;
197pub type OpenMlsRustCrypto = openmls_rust_crypto::OpenMlsRustCrypto;