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